Skip to content

Commit cdc5493

Browse files
committed
Auto merge of rust-lang#13327 - Veykril:proc-macro-srv-config, r=Veykril
Add config for supplying sysroot path
2 parents bf5cad8 + 5424c51 commit cdc5493

File tree

10 files changed

+87
-40
lines changed

10 files changed

+87
-40
lines changed

crates/project-model/src/cargo_workspace.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,8 @@ pub struct CargoConfig {
9494
pub features: CargoFeatures,
9595
/// rustc target
9696
pub target: Option<String>,
97-
/// Don't load sysroot crates (`std`, `core` & friends). Might be useful
98-
/// when debugging isolated issues.
99-
pub no_sysroot: bool,
97+
/// Sysroot loading behavior
98+
pub sysroot: Option<RustcSource>,
10099
/// rustc private crate source
101100
pub rustc_source: Option<RustcSource>,
102101
/// crates to disable `#[cfg(test)]` on

crates/project-model/src/sysroot.rs

+29-13
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,14 @@ impl Sysroot {
6767
pub fn crates<'a>(&'a self) -> impl Iterator<Item = SysrootCrate> + ExactSizeIterator + 'a {
6868
self.crates.iter().map(|(id, _data)| id)
6969
}
70+
}
7071

72+
impl Sysroot {
7173
pub fn discover(dir: &AbsPath, extra_env: &FxHashMap<String, String>) -> Result<Sysroot> {
7274
tracing::debug!("Discovering sysroot for {}", dir.display());
7375
let sysroot_dir = discover_sysroot_dir(dir, extra_env)?;
74-
let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, dir, extra_env)?;
76+
let sysroot_src_dir =
77+
discover_sysroot_src_dir_or_add_component(&sysroot_dir, dir, extra_env)?;
7578
let res = Sysroot::load(sysroot_dir, sysroot_src_dir)?;
7679
Ok(res)
7780
}
@@ -87,6 +90,14 @@ impl Sysroot {
8790
.and_then(|sysroot_dir| get_rustc_src(&sysroot_dir))
8891
}
8992

93+
pub fn with_sysroot_dir(sysroot_dir: AbsPathBuf) -> Result<Sysroot> {
94+
let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir).ok_or_else(|| {
95+
format_err!("can't load standard library from sysroot {}", sysroot_dir.display())
96+
})?;
97+
let res = Sysroot::load(sysroot_dir, sysroot_src_dir)?;
98+
Ok(res)
99+
}
100+
90101
pub fn load(sysroot_dir: AbsPathBuf, sysroot_src_dir: AbsPathBuf) -> Result<Sysroot> {
91102
let mut sysroot =
92103
Sysroot { root: sysroot_dir, src_root: sysroot_src_dir, crates: Arena::default() };
@@ -162,23 +173,28 @@ fn discover_sysroot_dir(
162173
Ok(AbsPathBuf::assert(PathBuf::from(stdout)))
163174
}
164175

165-
fn discover_sysroot_src_dir(
166-
sysroot_path: &AbsPathBuf,
167-
current_dir: &AbsPath,
168-
extra_env: &FxHashMap<String, String>,
169-
) -> Result<AbsPathBuf> {
176+
fn discover_sysroot_src_dir(sysroot_path: &AbsPathBuf) -> Option<AbsPathBuf> {
170177
if let Ok(path) = env::var("RUST_SRC_PATH") {
171-
let path = AbsPathBuf::try_from(path.as_str())
172-
.map_err(|path| format_err!("RUST_SRC_PATH must be absolute: {}", path.display()))?;
173-
let core = path.join("core");
174-
if fs::metadata(&core).is_ok() {
175-
tracing::debug!("Discovered sysroot by RUST_SRC_PATH: {}", path.display());
176-
return Ok(path);
178+
if let Ok(path) = AbsPathBuf::try_from(path.as_str()) {
179+
let core = path.join("core");
180+
if fs::metadata(&core).is_ok() {
181+
tracing::debug!("Discovered sysroot by RUST_SRC_PATH: {}", path.display());
182+
return Some(path);
183+
}
184+
tracing::debug!("RUST_SRC_PATH is set, but is invalid (no core: {:?}), ignoring", core);
185+
} else {
186+
tracing::debug!("RUST_SRC_PATH is set, but is invalid, ignoring");
177187
}
178-
tracing::debug!("RUST_SRC_PATH is set, but is invalid (no core: {:?}), ignoring", core);
179188
}
180189

181190
get_rust_src(sysroot_path)
191+
}
192+
fn discover_sysroot_src_dir_or_add_component(
193+
sysroot_path: &AbsPathBuf,
194+
current_dir: &AbsPath,
195+
extra_env: &FxHashMap<String, String>,
196+
) -> Result<AbsPathBuf> {
197+
discover_sysroot_src_dir(sysroot_path)
182198
.or_else(|| {
183199
let mut rustup = Command::new(toolchain::rustup());
184200
rustup.envs(extra_env);

crates/project-model/src/workspace.rs

+16-7
Original file line numberDiff line numberDiff line change
@@ -188,17 +188,26 @@ impl ProjectWorkspace {
188188
})?;
189189
let cargo = CargoWorkspace::new(meta);
190190

191-
let sysroot = if config.no_sysroot {
192-
None
193-
} else {
194-
Some(Sysroot::discover(cargo_toml.parent(), &config.extra_env).with_context(
195-
|| {
191+
let sysroot = match &config.sysroot {
192+
Some(RustcSource::Path(path)) => {
193+
Some(Sysroot::with_sysroot_dir(path.clone()).with_context(|| {
196194
format!(
195+
"Failed to find sysroot for Cargo.toml file {}.",
196+
cargo_toml.display()
197+
)
198+
})?)
199+
}
200+
Some(RustcSource::Discover) => Some(
201+
Sysroot::discover(cargo_toml.parent(), &config.extra_env).with_context(
202+
|| {
203+
format!(
197204
"Failed to find sysroot for Cargo.toml file {}. Is rust-src installed?",
198205
cargo_toml.display()
199206
)
200-
},
201-
)?)
207+
},
208+
)?,
209+
),
210+
None => None,
202211
};
203212

204213
let rustc_dir = match &config.rustc_source {

crates/rust-analyzer/src/cli/analysis_stats.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use ide_db::base_db::{
2424
use itertools::Itertools;
2525
use oorandom::Rand32;
2626
use profile::{Bytes, StopWatch};
27-
use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace};
27+
use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustcSource};
2828
use rayon::prelude::*;
2929
use rustc_hash::FxHashSet;
3030
use stdx::format_to;
@@ -55,7 +55,10 @@ impl flags::AnalysisStats {
5555
};
5656

5757
let mut cargo_config = CargoConfig::default();
58-
cargo_config.no_sysroot = self.no_sysroot;
58+
cargo_config.sysroot = match self.no_sysroot {
59+
true => None,
60+
false => Some(RustcSource::Discover),
61+
};
5962
let load_cargo_config = LoadCargoConfig {
6063
load_out_dirs_from_check: !self.disable_build_scripts,
6164
with_proc_macro: !self.disable_proc_macros,

crates/rust-analyzer/src/config.rs

+15-3
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,13 @@ config_data! {
9494
cargo_features: CargoFeaturesDef = "[]",
9595
/// Whether to pass `--no-default-features` to cargo.
9696
cargo_noDefaultFeatures: bool = "false",
97-
/// Internal config for debugging, disables loading of sysroot crates.
98-
cargo_noSysroot: bool = "false",
97+
/// Relative path to the sysroot, or "discover" to try to automatically find it via
98+
/// "rustc --print sysroot".
99+
///
100+
/// Unsetting this disables sysroot loading.
101+
///
102+
/// This option does not take effect until rust-analyzer is restarted.
103+
cargo_sysroot: Option<String> = "\"discover\"",
99104
/// Compilation target override (target triple).
100105
cargo_target: Option<String> = "null",
101106
/// Unsets `#[cfg(test)]` for the specified crates.
@@ -1030,6 +1035,13 @@ impl Config {
10301035
RustcSource::Path(self.root_path.join(rustc_src))
10311036
}
10321037
});
1038+
let sysroot = self.data.cargo_sysroot.as_ref().map(|sysroot| {
1039+
if sysroot == "discover" {
1040+
RustcSource::Discover
1041+
} else {
1042+
RustcSource::Path(self.root_path.join(sysroot))
1043+
}
1044+
});
10331045

10341046
CargoConfig {
10351047
features: match &self.data.cargo_features {
@@ -1040,7 +1052,7 @@ impl Config {
10401052
},
10411053
},
10421054
target: self.data.cargo_target.clone(),
1043-
no_sysroot: self.data.cargo_noSysroot,
1055+
sysroot,
10441056
rustc_source,
10451057
unset_test_crates: UnsetTestCrates::Only(self.data.cargo_unsetTest.clone()),
10461058
wrap_rustc_in_build_scripts: self.data.cargo_buildScripts_useRustcWrapper,

crates/rust-analyzer/tests/slow-tests/main.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ use std::collections::Spam;
5959
"#,
6060
)
6161
.with_config(serde_json::json!({
62-
"cargo": { "noSysroot": false }
62+
"cargo": { "sysroot": "discover" }
6363
}))
6464
.server()
6565
.wait_until_workspace_is_loaded();
@@ -614,7 +614,7 @@ fn main() {{}}
614614
librs, libs
615615
))
616616
.with_config(serde_json::json!({
617-
"cargo": { "noSysroot": false }
617+
"cargo": { "sysroot": "discover" }
618618
}))
619619
.server()
620620
.wait_until_workspace_is_loaded();
@@ -742,7 +742,7 @@ fn main() {
742742
"buildScripts": {
743743
"enable": true
744744
},
745-
"noSysroot": true,
745+
"sysroot": null,
746746
}
747747
}))
748748
.server()
@@ -900,7 +900,7 @@ pub fn foo(_input: TokenStream) -> TokenStream {
900900
"buildScripts": {
901901
"enable": true
902902
},
903-
"noSysroot": true,
903+
"sysroot": null,
904904
},
905905
"procMacro": {
906906
"enable": true,

crates/rust-analyzer/tests/slow-tests/support.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ impl<'a> Project<'a> {
3434
config: serde_json::json!({
3535
"cargo": {
3636
// Loading standard library is costly, let's ignore it by default
37-
"noSysroot": true,
37+
"sysroot": null,
3838
// Can't use test binary as rustc wrapper.
3939
"buildScripts": {
4040
"useRustcWrapper": false

docs/dev/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ After I am done with the fix, I use `cargo xtask install --client` to try the ne
9898
If I need to fix something in the `rust-analyzer` crate, I feel sad because it's on the boundary between the two processes, and working there is slow.
9999
I usually just `cargo xtask install --server` and poke changes from my live environment.
100100
Note that this uses `--release`, which is usually faster overall, because loading stdlib into debug version of rust-analyzer takes a lot of time.
101-
To speed things up, sometimes I open a temporary hello-world project which has `"rust-analyzer.cargo.noSysroot": true` in `.code/settings.json`.
101+
To speed things up, sometimes I open a temporary hello-world project which has `"rust-analyzer.cargo.sysroot": null` in `.code/settings.json`.
102102
This flag causes rust-analyzer to skip loading the sysroot, which greatly reduces the amount of things rust-analyzer needs to do, and makes printf's more useful.
103103
Note that you should only use the `eprint!` family of macros for debugging: stdout is used for LSP communication, and `print!` would break it.
104104

docs/user/generated_config.adoc

+7-2
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,15 @@ Set this to `"all"` to pass `--all-features` to cargo.
6464
--
6565
Whether to pass `--no-default-features` to cargo.
6666
--
67-
[[rust-analyzer.cargo.noSysroot]]rust-analyzer.cargo.noSysroot (default: `false`)::
67+
[[rust-analyzer.cargo.sysroot]]rust-analyzer.cargo.sysroot (default: `"discover"`)::
6868
+
6969
--
70-
Internal config for debugging, disables loading of sysroot crates.
70+
Relative path to the sysroot, or "discover" to try to automatically find it via
71+
"rustc --print sysroot".
72+
73+
Unsetting this disables sysroot loading.
74+
75+
This option does not take effect until rust-analyzer is restarted.
7176
--
7277
[[rust-analyzer.cargo.target]]rust-analyzer.cargo.target (default: `null`)::
7378
+

editors/code/package.json

+7-4
Original file line numberDiff line numberDiff line change
@@ -468,10 +468,13 @@
468468
"default": false,
469469
"type": "boolean"
470470
},
471-
"rust-analyzer.cargo.noSysroot": {
472-
"markdownDescription": "Internal config for debugging, disables loading of sysroot crates.",
473-
"default": false,
474-
"type": "boolean"
471+
"rust-analyzer.cargo.sysroot": {
472+
"markdownDescription": "Relative path to the sysroot, or \"discover\" to try to automatically find it via\n\"rustc --print sysroot\".\n\nUnsetting this disables sysroot loading.\n\nThis option does not take effect until rust-analyzer is restarted.",
473+
"default": "discover",
474+
"type": [
475+
"null",
476+
"string"
477+
]
475478
},
476479
"rust-analyzer.cargo.target": {
477480
"markdownDescription": "Compilation target override (target triple).",

0 commit comments

Comments
 (0)