Skip to content

Commit d50a37d

Browse files
bors[bot]bnjbvrCertainLach
authored
Merge #7643 #7663
7643: Automatically detect the rustc-src directory (fixes #3517) r=matklad a=bnjbvr If the configured rustcSource was not set, then try to automatically detect a source for the sysroot rustc directory. I wasn't sure how to do it in the case of the project.json file, though. 7663: Tolerate spaces in nix binary patching r=matklad a=CertainLach If path to original file contains space (I.e on code insiders, where default data directory is ~/Code - Insiders/), then there is syntax error evaluating src arg. Instead pass path as str, and coerce to path back in nix expression Co-authored-by: Benjamin Bouvier <public@benj.me> Co-authored-by: Yaroslav Bolyukin <iam@lach.pw>
3 parents 63c5c92 + 4a6e602 + 471795b commit d50a37d

File tree

8 files changed

+70
-23
lines changed

8 files changed

+70
-23
lines changed

crates/project_model/src/cargo_workspace.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,15 @@ impl ops::Index<Target> for CargoWorkspace {
4444
}
4545
}
4646

47+
/// Describes how to set the rustc source directory.
48+
#[derive(Clone, Debug, PartialEq, Eq)]
49+
pub enum RustcSource {
50+
/// Explicit path for the rustc source directory.
51+
Path(AbsPathBuf),
52+
/// Try to automatically detect where the rustc source directory is.
53+
Discover,
54+
}
55+
4756
#[derive(Default, Clone, Debug, PartialEq, Eq)]
4857
pub struct CargoConfig {
4958
/// Do not activate the `default` feature.
@@ -64,7 +73,7 @@ pub struct CargoConfig {
6473
pub no_sysroot: bool,
6574

6675
/// rustc private crate source
67-
pub rustc_source: Option<AbsPathBuf>,
76+
pub rustc_source: Option<RustcSource>,
6877
}
6978

7079
pub type Package = Idx<PackageData>;

crates/project_model/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ use rustc_hash::FxHashSet;
2121
pub use crate::{
2222
build_data::{BuildDataCollector, BuildDataResult},
2323
cargo_workspace::{
24-
CargoConfig, CargoWorkspace, Package, PackageData, PackageDependency, Target, TargetData,
25-
TargetKind,
24+
CargoConfig, CargoWorkspace, Package, PackageData, PackageDependency, RustcSource, Target,
25+
TargetData, TargetKind,
2626
},
2727
project_json::{ProjectJson, ProjectJsonData},
2828
sysroot::Sysroot,

crates/project_model/src/sysroot.rs

+30-10
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,18 @@ impl Sysroot {
5151
pub fn discover(cargo_toml: &AbsPath) -> Result<Sysroot> {
5252
log::debug!("Discovering sysroot for {}", cargo_toml.display());
5353
let current_dir = cargo_toml.parent().unwrap();
54-
let sysroot_src_dir = discover_sysroot_src_dir(current_dir)?;
54+
let sysroot_dir = discover_sysroot_dir(current_dir)?;
55+
let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, current_dir)?;
5556
let res = Sysroot::load(&sysroot_src_dir)?;
5657
Ok(res)
5758
}
5859

60+
pub fn discover_rustc(cargo_toml: &AbsPath) -> Option<AbsPathBuf> {
61+
log::debug!("Discovering rustc source for {}", cargo_toml.display());
62+
let current_dir = cargo_toml.parent().unwrap();
63+
discover_sysroot_dir(current_dir).ok().and_then(|sysroot_dir| get_rustc_src(&sysroot_dir))
64+
}
65+
5966
pub fn load(sysroot_src_dir: &AbsPath) -> Result<Sysroot> {
6067
let mut sysroot = Sysroot { crates: Arena::default() };
6168

@@ -110,7 +117,18 @@ impl Sysroot {
110117
}
111118
}
112119

113-
fn discover_sysroot_src_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
120+
fn discover_sysroot_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
121+
let mut rustc = Command::new(toolchain::rustc());
122+
rustc.current_dir(current_dir).args(&["--print", "sysroot"]);
123+
log::debug!("Discovering sysroot by {:?}", rustc);
124+
let stdout = utf8_stdout(rustc)?;
125+
Ok(AbsPathBuf::assert(PathBuf::from(stdout)))
126+
}
127+
128+
fn discover_sysroot_src_dir(
129+
sysroot_path: &AbsPathBuf,
130+
current_dir: &AbsPath,
131+
) -> Result<AbsPathBuf> {
114132
if let Ok(path) = env::var("RUST_SRC_PATH") {
115133
let path = AbsPathBuf::try_from(path.as_str())
116134
.map_err(|path| format_err!("RUST_SRC_PATH must be absolute: {}", path.display()))?;
@@ -122,14 +140,6 @@ fn discover_sysroot_src_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
122140
log::debug!("RUST_SRC_PATH is set, but is invalid (no core: {:?}), ignoring", core);
123141
}
124142

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-
133143
get_rust_src(&sysroot_path)
134144
.or_else(|| {
135145
let mut rustup = Command::new(toolchain::rustup());
@@ -149,6 +159,16 @@ try installing the Rust source the same way you installed rustc",
149159
})
150160
}
151161

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

crates/project_model/src/workspace.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ impl ProjectWorkspace {
114114
cargo_version
115115
)
116116
})?;
117+
117118
let sysroot = if config.no_sysroot {
118119
Sysroot::default()
119120
} else {
@@ -125,7 +126,17 @@ impl ProjectWorkspace {
125126
})?
126127
};
127128

128-
let rustc = if let Some(rustc_dir) = &config.rustc_source {
129+
let rustc_dir = if let Some(rustc_source) = &config.rustc_source {
130+
use cargo_workspace::RustcSource;
131+
match rustc_source {
132+
RustcSource::Path(path) => Some(path.clone()),
133+
RustcSource::Discover => Sysroot::discover_rustc(&cargo_toml),
134+
}
135+
} else {
136+
None
137+
};
138+
139+
let rustc = if let Some(rustc_dir) = rustc_dir {
129140
Some(
130141
CargoWorkspace::from_cargo_metadata(&rustc_dir, config, progress)
131142
.with_context(|| {

crates/rust-analyzer/src/config.rs

+11-4
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use ide_db::helpers::{
1818
};
1919
use itertools::Itertools;
2020
use lsp_types::{ClientCapabilities, MarkupKind};
21-
use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest};
21+
use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest, RustcSource};
2222
use rustc_hash::FxHashSet;
2323
use serde::{de::DeserializeOwned, Deserialize};
2424
use vfs::AbsPathBuf;
@@ -177,8 +177,9 @@ config_data! {
177177
/// tests or binaries.\nFor example, it may be `--release`.
178178
runnables_cargoExtraArgs: Vec<String> = "[]",
179179

180-
/// Path to the rust compiler sources, for usage in rustc_private projects.
181-
rustcSource : Option<PathBuf> = "null",
180+
/// Path to the rust compiler sources, for usage in rustc_private projects, or "discover"
181+
/// to try to automatically find it.
182+
rustcSource : Option<String> = "null",
182183

183184
/// Additional arguments to `rustfmt`.
184185
rustfmt_extraArgs: Vec<String> = "[]",
@@ -473,7 +474,13 @@ impl Config {
473474
self.data.cargo_loadOutDirsFromCheck
474475
}
475476
pub fn cargo(&self) -> CargoConfig {
476-
let rustc_source = self.data.rustcSource.as_ref().map(|it| self.root_path.join(&it));
477+
let rustc_source = self.data.rustcSource.as_ref().map(|rustc_src| {
478+
if rustc_src == "discover" {
479+
RustcSource::Discover
480+
} else {
481+
RustcSource::Path(self.root_path.join(rustc_src))
482+
}
483+
});
477484

478485
CargoConfig {
479486
no_default_features: self.data.cargo_noDefaultFeatures,

docs/user/generated_config.adoc

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@
105105
[[rust-analyzer.runnables.cargoExtraArgs]]rust-analyzer.runnables.cargoExtraArgs (default: `[]`)::
106106
Additional arguments to be passed to cargo for runnables such as tests or binaries.\nFor example, it may be `--release`.
107107
[[rust-analyzer.rustcSource]]rust-analyzer.rustcSource (default: `null`)::
108-
Path to the rust compiler sources, for usage in rustc_private projects.
108+
Path to the rust compiler sources, for usage in rustc_private projects, or "discover" to try to automatically find it.
109109
[[rust-analyzer.rustfmt.extraArgs]]rust-analyzer.rustfmt.extraArgs (default: `[]`)::
110110
Additional arguments to `rustfmt`.
111111
[[rust-analyzer.rustfmt.overrideCommand]]rust-analyzer.rustfmt.overrideCommand (default: `null`)::

editors/code/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,7 @@
707707
}
708708
},
709709
"rust-analyzer.rustcSource": {
710-
"markdownDescription": "Path to the rust compiler sources, for usage in rustc_private projects.",
710+
"markdownDescription": "Path to the rust compiler sources, for usage in rustc_private projects, or \"discover\" to try to automatically find it.",
711711
"default": null,
712712
"type": [
713713
"null",

editors/code/src/main.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -246,10 +246,10 @@ async function patchelf(dest: PathLike): Promise<void> {
246246
},
247247
async (progress, _) => {
248248
const expression = `
249-
{src, pkgs ? import <nixpkgs> {}}:
249+
{srcStr, pkgs ? import <nixpkgs> {}}:
250250
pkgs.stdenv.mkDerivation {
251251
name = "rust-analyzer";
252-
inherit src;
252+
src = /. + srcStr;
253253
phases = [ "installPhase" "fixupPhase" ];
254254
installPhase = "cp $src $out";
255255
fixupPhase = ''
@@ -262,7 +262,7 @@ async function patchelf(dest: PathLike): Promise<void> {
262262
await fs.rename(dest, origFile);
263263
progress.report({ message: "Patching executable", increment: 20 });
264264
await new Promise((resolve, reject) => {
265-
const handle = exec(`nix-build -E - --arg src '${origFile}' -o ${dest}`,
265+
const handle = exec(`nix-build -E - --argstr srcStr '${origFile}' -o '${dest}'`,
266266
(err, stdout, stderr) => {
267267
if (err != null) {
268268
reject(Error(stderr));

0 commit comments

Comments
 (0)