Skip to content

Commit cb9a5b9

Browse files
committed
Support sysroot library source being defined inside the workspace
1 parent 0b32b65 commit cb9a5b9

File tree

6 files changed

+68
-9
lines changed

6 files changed

+68
-9
lines changed

crates/project-model/src/cargo_workspace.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ pub struct CargoConfig {
9696
pub target: Option<String>,
9797
/// Sysroot loading behavior
9898
pub sysroot: Option<RustcSource>,
99+
pub sysroot_src: Option<AbsPathBuf>,
99100
/// rustc private crate source
100101
pub rustc_source: Option<RustcSource>,
101102
/// crates to disable `#[cfg(test)]` on

crates/project-model/src/sysroot.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ impl Sysroot {
7676
}
7777
}
7878

79+
// FIXME: Expose a builder api as loading the sysroot got way too modular and complicated.
7980
impl Sysroot {
8081
/// Attempts to discover the toolchain's sysroot from the given `dir`.
8182
pub fn discover(dir: &AbsPath, extra_env: &FxHashMap<String, String>) -> Result<Sysroot> {
@@ -86,6 +87,16 @@ impl Sysroot {
8687
Ok(Sysroot::load(sysroot_dir, sysroot_src_dir))
8788
}
8889

90+
pub fn discover_with_src_override(
91+
dir: &AbsPath,
92+
extra_env: &FxHashMap<String, String>,
93+
src: AbsPathBuf,
94+
) -> Result<Sysroot> {
95+
tracing::debug!("discovering sysroot for {}", dir.display());
96+
let sysroot_dir = discover_sysroot_dir(dir, extra_env)?;
97+
Ok(Sysroot::load(sysroot_dir, src))
98+
}
99+
89100
pub fn discover_rustc(
90101
cargo_toml: &ManifestPath,
91102
extra_env: &FxHashMap<String, String>,

crates/project-model/src/workspace.rs

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,8 @@ impl ProjectWorkspace {
190190
})?;
191191
let cargo = CargoWorkspace::new(meta);
192192

193-
let sysroot = match &config.sysroot {
194-
Some(RustcSource::Path(path)) => {
193+
let sysroot = match (&config.sysroot, &config.sysroot_src) {
194+
(Some(RustcSource::Path(path)), None) => {
195195
match Sysroot::with_sysroot_dir(path.clone()) {
196196
Ok(it) => Some(it),
197197
Err(e) => {
@@ -200,7 +200,7 @@ impl ProjectWorkspace {
200200
}
201201
}
202202
}
203-
Some(RustcSource::Discover) => {
203+
(Some(RustcSource::Discover), None) => {
204204
match Sysroot::discover(cargo_toml.parent(), &config.extra_env) {
205205
Ok(it) => Some(it),
206206
Err(e) => {
@@ -213,8 +213,29 @@ impl ProjectWorkspace {
213213
}
214214
}
215215
}
216-
None => None,
216+
(Some(RustcSource::Path(sysroot)), Some(sysroot_src)) => {
217+
Some(Sysroot::load(sysroot.clone(), sysroot_src.clone()))
218+
}
219+
(Some(RustcSource::Discover), Some(sysroot_src)) => {
220+
match Sysroot::discover_with_src_override(
221+
cargo_toml.parent(),
222+
&config.extra_env,
223+
sysroot_src.clone(),
224+
) {
225+
Ok(it) => Some(it),
226+
Err(e) => {
227+
tracing::error!(
228+
%e,
229+
"Failed to find sysroot for Cargo.toml file {}. Is rust-src installed?",
230+
cargo_toml.display()
231+
);
232+
None
233+
}
234+
}
235+
}
236+
(None, _) => None,
217237
};
238+
218239
if let Some(sysroot) = &sysroot {
219240
tracing::info!(src_root = %sysroot.src_root().display(), root = %sysroot.root().display(), "Using sysroot");
220241
}
@@ -440,9 +461,11 @@ impl ProjectWorkspace {
440461
/// The return type contains the path and whether or not
441462
/// the root is a member of the current workspace
442463
pub fn to_roots(&self) -> Vec<PackageRoot> {
443-
let mk_sysroot = |sysroot: Option<&Sysroot>| {
464+
let mk_sysroot = |sysroot: Option<&Sysroot>, project_root: Option<&AbsPath>| {
444465
sysroot.map(|sysroot| PackageRoot {
445-
is_local: false,
466+
// mark the sysroot as mutable if it is located inside of the project
467+
is_local: project_root
468+
.map_or(false, |project_root| sysroot.src_root().starts_with(project_root)),
446469
include: vec![sysroot.src_root().to_path_buf()],
447470
exclude: Vec::new(),
448471
})
@@ -457,7 +480,7 @@ impl ProjectWorkspace {
457480
})
458481
.collect::<FxHashSet<_>>()
459482
.into_iter()
460-
.chain(mk_sysroot(sysroot.as_ref()))
483+
.chain(mk_sysroot(sysroot.as_ref(), Some(project.path())))
461484
.collect::<Vec<_>>(),
462485
ProjectWorkspace::Cargo {
463486
cargo,
@@ -507,7 +530,7 @@ impl ProjectWorkspace {
507530
}
508531
PackageRoot { is_local, include, exclude }
509532
})
510-
.chain(mk_sysroot(sysroot.as_ref()))
533+
.chain(mk_sysroot(sysroot.as_ref(), Some(cargo.workspace_root())))
511534
.chain(rustc.iter().flat_map(|rustc| {
512535
rustc.packages().map(move |krate| PackageRoot {
513536
is_local: false,
@@ -524,7 +547,7 @@ impl ProjectWorkspace {
524547
include: vec![detached_file.clone()],
525548
exclude: Vec::new(),
526549
})
527-
.chain(mk_sysroot(sysroot.as_ref()))
550+
.chain(mk_sysroot(sysroot.as_ref(), None))
528551
.collect(),
529552
}
530553
}

crates/rust-analyzer/src/config.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ config_data! {
117117
///
118118
/// This option does not take effect until rust-analyzer is restarted.
119119
cargo_sysroot: Option<String> = "\"discover\"",
120+
/// Relative path to the sysroot library sources. If left unset, this will default to
121+
/// `{cargo.sysroot}/lib/rustlib/src/rust/library`.
122+
///
123+
/// This option does not take effect until rust-analyzer is restarted.
124+
cargo_sysrootSrc: Option<String> = "null",
120125
/// Compilation target override (target triple).
121126
// FIXME(@poliorcetics): move to multiple targets here too, but this will need more work
122127
// than `checkOnSave_target`
@@ -1103,6 +1108,8 @@ impl Config {
11031108
RustcSource::Path(self.root_path.join(sysroot))
11041109
}
11051110
});
1111+
let sysroot_src =
1112+
self.data.cargo_sysrootSrc.as_ref().map(|sysroot| self.root_path.join(sysroot));
11061113

11071114
CargoConfig {
11081115
features: match &self.data.cargo_features {
@@ -1114,6 +1121,7 @@ impl Config {
11141121
},
11151122
target: self.data.cargo_target.clone(),
11161123
sysroot,
1124+
sysroot_src,
11171125
rustc_source,
11181126
unset_test_crates: UnsetTestCrates::Only(self.data.cargo_unsetTest.clone()),
11191127
wrap_rustc_in_build_scripts: self.data.cargo_buildScripts_useRustcWrapper,

docs/user/generated_config.adoc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,14 @@ Relative path to the sysroot, or "discover" to try to automatically find it via
9797

9898
Unsetting this disables sysroot loading.
9999

100+
This option does not take effect until rust-analyzer is restarted.
101+
--
102+
[[rust-analyzer.cargo.sysrootSrc]]rust-analyzer.cargo.sysrootSrc (default: `null`)::
103+
+
104+
--
105+
Relative path to the sysroot library sources. If left unset, this will default to
106+
`{cargo.sysroot}/lib/rustlib/src/rust/library`.
107+
100108
This option does not take effect until rust-analyzer is restarted.
101109
--
102110
[[rust-analyzer.cargo.target]]rust-analyzer.cargo.target (default: `null`)::

editors/code/package.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,14 @@
539539
"string"
540540
]
541541
},
542+
"rust-analyzer.cargo.sysrootSrc": {
543+
"markdownDescription": "Relative path to the sysroot library sources. If left unset, this will default to\n`{cargo.sysroot}/lib/rustlib/src/rust/library`.\n\nThis option does not take effect until rust-analyzer is restarted.",
544+
"default": null,
545+
"type": [
546+
"null",
547+
"string"
548+
]
549+
},
542550
"rust-analyzer.cargo.target": {
543551
"markdownDescription": "Compilation target override (target triple).",
544552
"default": null,

0 commit comments

Comments
 (0)