Skip to content

Commit e7b6c4f

Browse files
committed
Automatically detect the rustc-src directory (fixes #3517).
If the configured rustcSource was not set, then try to automatically detect a source for the sysroot rustc directory.
1 parent 3ab8d7a commit e7b6c4f

File tree

2 files changed

+40
-15
lines changed

2 files changed

+40
-15
lines changed

crates/project_model/src/sysroot.rs

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::utf8_stdout;
1515
#[derive(Default, Debug, Clone, Eq, PartialEq)]
1616
pub struct Sysroot {
1717
crates: Arena<SysrootCrateData>,
18+
pub rustc_src_dir: Option<AbsPathBuf>,
1819
}
1920

2021
pub(crate) type SysrootCrate = Idx<SysrootCrateData>;
@@ -51,13 +52,15 @@ impl Sysroot {
5152
pub fn discover(cargo_toml: &AbsPath) -> Result<Sysroot> {
5253
log::debug!("Discovering sysroot for {}", cargo_toml.display());
5354
let current_dir = cargo_toml.parent().unwrap();
54-
let sysroot_src_dir = discover_sysroot_src_dir(current_dir)?;
55-
let res = Sysroot::load(&sysroot_src_dir)?;
55+
let sysroot_dir = discover_sysroot_dir(current_dir)?;
56+
let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, current_dir)?;
57+
let rustc_src_dir = get_rustc_src(&sysroot_dir);
58+
let res = Sysroot::load(&sysroot_src_dir, rustc_src_dir)?;
5659
Ok(res)
5760
}
5861

59-
pub fn load(sysroot_src_dir: &AbsPath) -> Result<Sysroot> {
60-
let mut sysroot = Sysroot { crates: Arena::default() };
62+
pub fn load(sysroot_src_dir: &AbsPath, rustc_src_dir: Option<AbsPathBuf>) -> Result<Sysroot> {
63+
let mut sysroot = Sysroot { crates: Arena::default(), rustc_src_dir };
6164

6265
for name in SYSROOT_CRATES.trim().lines() {
6366
let root = [format!("{}/src/lib.rs", name), format!("lib{}/lib.rs", name)]
@@ -110,7 +113,18 @@ impl Sysroot {
110113
}
111114
}
112115

113-
fn discover_sysroot_src_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
116+
fn discover_sysroot_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
117+
let mut rustc = Command::new(toolchain::rustc());
118+
rustc.current_dir(current_dir).args(&["--print", "sysroot"]);
119+
log::debug!("Discovering sysroot by {:?}", rustc);
120+
let stdout = utf8_stdout(rustc)?;
121+
Ok(AbsPathBuf::assert(PathBuf::from(stdout)))
122+
}
123+
124+
fn discover_sysroot_src_dir(
125+
sysroot_path: &AbsPathBuf,
126+
current_dir: &AbsPath,
127+
) -> Result<AbsPathBuf> {
114128
if let Ok(path) = env::var("RUST_SRC_PATH") {
115129
let path = AbsPathBuf::try_from(path.as_str())
116130
.map_err(|path| format_err!("RUST_SRC_PATH must be absolute: {}", path.display()))?;
@@ -122,14 +136,6 @@ fn discover_sysroot_src_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
122136
log::debug!("RUST_SRC_PATH is set, but is invalid (no core: {:?}), ignoring", core);
123137
}
124138

125-
let sysroot_path = {
126-
let mut rustc = Command::new(toolchain::rustc());
127-
rustc.current_dir(current_dir).args(&["--print", "sysroot"]);
128-
log::debug!("Discovering sysroot by {:?}", rustc);
129-
let stdout = utf8_stdout(rustc)?;
130-
AbsPathBuf::assert(PathBuf::from(stdout))
131-
};
132-
133139
get_rust_src(&sysroot_path)
134140
.or_else(|| {
135141
let mut rustup = Command::new(toolchain::rustup());
@@ -149,6 +155,16 @@ try installing the Rust source the same way you installed rustc",
149155
})
150156
}
151157

158+
fn get_rustc_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
159+
let rustc_src = sysroot_path.join("lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml");
160+
log::debug!("Checking for rustc source code: {}", rustc_src.display());
161+
if rustc_src.exists() {
162+
Some(rustc_src)
163+
} else {
164+
None
165+
}
166+
}
167+
152168
fn get_rust_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
153169
// Try the new path first since the old one still exists.
154170
let rust_src = sysroot_path.join("lib/rustlib/src/rust");

crates/project_model/src/workspace.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ impl ProjectWorkspace {
108108
cargo_version
109109
)
110110
})?;
111+
111112
let sysroot = if config.no_sysroot {
112113
Sysroot::default()
113114
} else {
@@ -119,7 +120,15 @@ impl ProjectWorkspace {
119120
})?
120121
};
121122

122-
let rustc = if let Some(rustc_dir) = &config.rustc_source {
123+
let rustc_dir = if let Some(rustc_dir) = &config.rustc_source {
124+
Some(rustc_dir)
125+
} else if let Some(rustc_dir) = &sysroot.rustc_src_dir {
126+
Some(rustc_dir)
127+
} else {
128+
None
129+
};
130+
131+
let rustc = if let Some(rustc_dir) = rustc_dir {
123132
Some(
124133
CargoWorkspace::from_cargo_metadata(&rustc_dir, config, progress)
125134
.with_context(|| {
@@ -142,7 +151,7 @@ impl ProjectWorkspace {
142151
target: Option<&str>,
143152
) -> Result<ProjectWorkspace> {
144153
let sysroot = match &project_json.sysroot_src {
145-
Some(path) => Some(Sysroot::load(path)?),
154+
Some(path) => Some(Sysroot::load(path, None)?),
146155
None => None,
147156
};
148157
let rustc_cfg = rustc_cfg::get(target);

0 commit comments

Comments
 (0)