Unnamed repository; edit this file 'description' to name the repository.
fix: Set RUSTUP_TOOLCHAIN and invoke the proxies instead of directly invoking sysroot binaries
Lukas Wirth 2024-02-14
parent 000ce5d · commit 465ddef
-rw-r--r--crates/flycheck/src/lib.rs23
-rw-r--r--crates/project-model/src/build_scripts.rs12
-rw-r--r--crates/project-model/src/cargo_workspace.rs10
-rw-r--r--crates/project-model/src/rustc_cfg.rs13
-rw-r--r--crates/project-model/src/sysroot.rs24
-rw-r--r--crates/project-model/src/target_data_layout.rs8
-rw-r--r--crates/project-model/src/workspace.rs30
-rw-r--r--crates/rust-analyzer/src/handlers/request.rs2
-rw-r--r--crates/rust-analyzer/src/reload.rs39
9 files changed, 82 insertions, 79 deletions
diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs
index 71882b6f0d..ee39a2790b 100644
--- a/crates/flycheck/src/lib.rs
+++ b/crates/flycheck/src/lib.rs
@@ -23,6 +23,7 @@ pub use cargo_metadata::diagnostic::{
Applicability, Diagnostic, DiagnosticCode, DiagnosticLevel, DiagnosticSpan,
DiagnosticSpanMacroExpansion,
};
+use toolchain::Tool;
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub enum InvocationStrategy {
@@ -89,10 +90,10 @@ impl FlycheckHandle {
id: usize,
sender: Box<dyn Fn(Message) + Send>,
config: FlycheckConfig,
- cargo: PathBuf,
+ sysroot_root: Option<AbsPathBuf>,
workspace_root: AbsPathBuf,
) -> FlycheckHandle {
- let actor = FlycheckActor::new(id, sender, config, cargo, workspace_root);
+ let actor = FlycheckActor::new(id, sender, config, sysroot_root, workspace_root);
let (sender, receiver) = unbounded::<StateChange>();
let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker)
.name("Flycheck".to_owned())
@@ -174,7 +175,7 @@ struct FlycheckActor {
/// Either the workspace root of the workspace we are flychecking,
/// or the project root of the project.
root: AbsPathBuf,
- cargo: PathBuf,
+ sysroot_root: Option<AbsPathBuf>,
/// CargoHandle exists to wrap around the communication needed to be able to
/// run `cargo check` without blocking. Currently the Rust standard library
/// doesn't provide a way to read sub-process output without blocking, so we
@@ -195,11 +196,18 @@ impl FlycheckActor {
id: usize,
sender: Box<dyn Fn(Message) + Send>,
config: FlycheckConfig,
- cargo: PathBuf,
+ sysroot_root: Option<AbsPathBuf>,
workspace_root: AbsPathBuf,
) -> FlycheckActor {
tracing::info!(%id, ?workspace_root, "Spawning flycheck");
- FlycheckActor { id, sender, config, cargo, root: workspace_root, command_handle: None }
+ FlycheckActor {
+ id,
+ sender,
+ config,
+ sysroot_root,
+ root: workspace_root,
+ command_handle: None,
+ }
}
fn report_progress(&self, progress: Progress) {
@@ -334,7 +342,10 @@ impl FlycheckActor {
ansi_color_output,
target_dir,
} => {
- let mut cmd = Command::new(&self.cargo);
+ let mut cmd = Command::new(Tool::Cargo.path());
+ if let Some(sysroot_root) = &self.sysroot_root {
+ cmd.env("RUSTUP_TOOLCHAIN", AsRef::<std::path::Path>::as_ref(sysroot_root));
+ }
cmd.arg(command);
cmd.current_dir(&self.root);
diff --git a/crates/project-model/src/build_scripts.rs b/crates/project-model/src/build_scripts.rs
index 51b9c8f576..98060e876a 100644
--- a/crates/project-model/src/build_scripts.rs
+++ b/crates/project-model/src/build_scripts.rs
@@ -71,10 +71,8 @@ impl WorkspaceBuildScripts {
cmd
}
_ => {
- let mut cmd = Command::new(
- Sysroot::discover_tool(sysroot, Tool::Cargo)
- .map_err(|e| io::Error::new(io::ErrorKind::NotFound, e))?,
- );
+ let mut cmd = Command::new(Tool::Cargo.path());
+ Sysroot::set_rustup_toolchain_env(&mut cmd, sysroot);
cmd.args(["check", "--quiet", "--workspace", "--message-format=json"]);
cmd.args(&config.extra_args);
@@ -431,7 +429,8 @@ impl WorkspaceBuildScripts {
}
let res = (|| {
let target_libdir = (|| {
- let mut cargo_config = Command::new(Sysroot::discover_tool(sysroot, Tool::Cargo)?);
+ let mut cargo_config = Command::new(Tool::Cargo.path());
+ Sysroot::set_rustup_toolchain_env(&mut cargo_config, sysroot);
cargo_config.envs(extra_env);
cargo_config
.current_dir(current_dir)
@@ -440,7 +439,8 @@ impl WorkspaceBuildScripts {
if let Ok(it) = utf8_stdout(cargo_config) {
return Ok(it);
}
- let mut cmd = Command::new(Sysroot::discover_tool(sysroot, Tool::Rustc)?);
+ let mut cmd = Command::new(Tool::Rustc.path());
+ Sysroot::set_rustup_toolchain_env(&mut cmd, sysroot);
cmd.envs(extra_env);
cmd.args(["--print", "target-libdir"]);
utf8_stdout(cmd)
diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs
index dae03afde2..8136dc221f 100644
--- a/crates/project-model/src/cargo_workspace.rs
+++ b/crates/project-model/src/cargo_workspace.rs
@@ -243,7 +243,7 @@ impl CargoWorkspace {
let targets = find_list_of_build_targets(config, cargo_toml, sysroot);
let mut meta = MetadataCommand::new();
- meta.cargo_path(Sysroot::discover_tool(sysroot, Tool::Cargo)?);
+ meta.cargo_path(Tool::Cargo.path());
meta.manifest_path(cargo_toml.to_path_buf());
match &config.features {
CargoFeatures::All => {
@@ -291,6 +291,7 @@ impl CargoWorkspace {
(|| -> Result<cargo_metadata::Metadata, cargo_metadata::Error> {
let mut command = meta.cargo_command();
+ Sysroot::set_rustup_toolchain_env(&mut command, sysroot);
command.envs(&config.extra_env);
let output = command.output()?;
if !output.status.success() {
@@ -500,7 +501,8 @@ fn rustc_discover_host_triple(
extra_env: &FxHashMap<String, String>,
sysroot: Option<&Sysroot>,
) -> Option<String> {
- let mut rustc = Command::new(Sysroot::discover_tool(sysroot, Tool::Rustc).ok()?);
+ let mut rustc = Command::new(Tool::Rustc.path());
+ Sysroot::set_rustup_toolchain_env(&mut rustc, sysroot);
rustc.envs(extra_env);
rustc.current_dir(cargo_toml.parent()).arg("-vV");
tracing::debug!("Discovering host platform by {:?}", rustc);
@@ -528,8 +530,8 @@ fn cargo_config_build_target(
extra_env: &FxHashMap<String, String>,
sysroot: Option<&Sysroot>,
) -> Vec<String> {
- let Ok(program) = Sysroot::discover_tool(sysroot, Tool::Cargo) else { return vec![] };
- let mut cargo_config = Command::new(program);
+ let mut cargo_config = Command::new(Tool::Cargo.path());
+ Sysroot::set_rustup_toolchain_env(&mut cargo_config, sysroot);
cargo_config.envs(extra_env);
cargo_config
.current_dir(cargo_toml.parent())
diff --git a/crates/project-model/src/rustc_cfg.rs b/crates/project-model/src/rustc_cfg.rs
index 1d07e4a8a6..1ad6e7255b 100644
--- a/crates/project-model/src/rustc_cfg.rs
+++ b/crates/project-model/src/rustc_cfg.rs
@@ -68,11 +68,11 @@ fn get_rust_cfgs(
config: RustcCfgConfig<'_>,
) -> anyhow::Result<String> {
let sysroot = match config {
- RustcCfgConfig::Cargo(sysroot, cargo_oml) => {
- let cargo = Sysroot::discover_tool(sysroot, toolchain::Tool::Cargo)?;
- let mut cmd = Command::new(cargo);
+ RustcCfgConfig::Cargo(sysroot, cargo_toml) => {
+ let mut cmd = Command::new(toolchain::Tool::Cargo.path());
+ Sysroot::set_rustup_toolchain_env(&mut cmd, sysroot);
cmd.envs(extra_env);
- cmd.current_dir(cargo_oml.parent())
+ cmd.current_dir(cargo_toml.parent())
.args(["rustc", "-Z", "unstable-options", "--print", "cfg"])
.env("RUSTC_BOOTSTRAP", "1");
if let Some(target) = target {
@@ -90,9 +90,8 @@ fn get_rust_cfgs(
RustcCfgConfig::Rustc(sysroot) => sysroot,
};
- let rustc = Sysroot::discover_tool(sysroot, toolchain::Tool::Rustc)?;
- tracing::debug!(?rustc, "using explicit rustc from sysroot");
- let mut cmd = Command::new(rustc);
+ let mut cmd = Command::new(toolchain::Tool::Rustc.path());
+ Sysroot::set_rustup_toolchain_env(&mut cmd, sysroot);
cmd.envs(extra_env);
cmd.args(["--print", "cfg", "-O"]);
if let Some(target) = target {
diff --git a/crates/project-model/src/sysroot.rs b/crates/project-model/src/sysroot.rs
index 24c2edd2c4..07cfaba2d2 100644
--- a/crates/project-model/src/sysroot.rs
+++ b/crates/project-model/src/sysroot.rs
@@ -6,13 +6,13 @@
use std::{env, fs, iter, ops, path::PathBuf, process::Command, sync::Arc};
-use anyhow::{format_err, Context, Result};
+use anyhow::{format_err, Result};
use base_db::CrateName;
use itertools::Itertools;
use la_arena::{Arena, Idx};
use paths::{AbsPath, AbsPathBuf};
use rustc_hash::FxHashMap;
-use toolchain::{probe_for_binary, Tool};
+use toolchain::probe_for_binary;
use crate::{utf8_stdout, CargoConfig, CargoWorkspace, ManifestPath};
@@ -193,23 +193,9 @@ impl Sysroot {
Ok(Sysroot::load(sysroot_dir, Some(sysroot_src_dir), metadata))
}
- pub fn discover_binary(&self, binary: &str) -> anyhow::Result<AbsPathBuf> {
- toolchain::probe_for_binary(self.root.join("bin").join(binary).into())
- .ok_or_else(|| anyhow::anyhow!("no rustc binary found in {}", self.root.join("bin")))
- .and_then(|rustc| {
- fs::metadata(&rustc).map(|_| AbsPathBuf::assert(rustc)).with_context(|| {
- format!(
- "failed to discover rustc in sysroot: {:?}",
- AsRef::<std::path::Path>::as_ref(&self.root)
- )
- })
- })
- }
-
- pub fn discover_tool(sysroot: Option<&Self>, tool: Tool) -> anyhow::Result<PathBuf> {
- match sysroot {
- Some(sysroot) => sysroot.discover_binary(tool.name()).map(Into::into),
- None => Ok(tool.path()),
+ pub fn set_rustup_toolchain_env(cmd: &mut Command, sysroot: Option<&Self>) {
+ if let Some(sysroot) = sysroot {
+ cmd.env("RUSTUP_TOOLCHAIN", AsRef::<std::path::Path>::as_ref(&sysroot.root));
}
}
diff --git a/crates/project-model/src/target_data_layout.rs b/crates/project-model/src/target_data_layout.rs
index 4c5200cee8..af635dda57 100644
--- a/crates/project-model/src/target_data_layout.rs
+++ b/crates/project-model/src/target_data_layout.rs
@@ -28,8 +28,8 @@ pub fn get(
};
let sysroot = match config {
RustcDataLayoutConfig::Cargo(sysroot, cargo_toml) => {
- let cargo = Sysroot::discover_tool(sysroot, toolchain::Tool::Cargo)?;
- let mut cmd = Command::new(cargo);
+ let mut cmd = Command::new(toolchain::Tool::Cargo.path());
+ Sysroot::set_rustup_toolchain_env(&mut cmd, sysroot);
cmd.envs(extra_env);
cmd.current_dir(cargo_toml.parent())
.args(["rustc", "--", "-Z", "unstable-options", "--print", "target-spec-json"])
@@ -48,8 +48,8 @@ pub fn get(
RustcDataLayoutConfig::Rustc(sysroot) => sysroot,
};
- let rustc = Sysroot::discover_tool(sysroot, toolchain::Tool::Rustc)?;
- let mut cmd = Command::new(rustc);
+ let mut cmd = Command::new(toolchain::Tool::Rustc.path());
+ Sysroot::set_rustup_toolchain_env(&mut cmd, sysroot);
cmd.envs(extra_env)
.args(["-Z", "unstable-options", "--print", "target-spec-json"])
.env("RUSTC_BOOTSTRAP", "1");
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index cacd506d1b..6a53fd00ae 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -2,9 +2,7 @@
//! metadata` or `rust-project.json`) into representation stored in the salsa
//! database -- `CrateGraph`.
-use std::{
- collections::VecDeque, fmt, fs, iter, path::PathBuf, process::Command, str::FromStr, sync,
-};
+use std::{collections::VecDeque, fmt, fs, iter, process::Command, str::FromStr, sync};
use anyhow::{format_err, Context};
use base_db::{
@@ -16,6 +14,7 @@ use paths::{AbsPath, AbsPathBuf};
use rustc_hash::{FxHashMap, FxHashSet};
use semver::Version;
use stdx::always;
+use toolchain::Tool;
use triomphe::Arc;
use crate::{
@@ -163,12 +162,14 @@ impl fmt::Debug for ProjectWorkspace {
fn get_toolchain_version(
current_dir: &AbsPath,
- cmd_path: Result<PathBuf, anyhow::Error>,
+ sysroot: Option<&Sysroot>,
+ tool: Tool,
extra_env: &FxHashMap<String, String>,
prefix: &str,
) -> Result<Option<Version>, anyhow::Error> {
let cargo_version = utf8_stdout({
- let mut cmd = Command::new(cmd_path?);
+ let mut cmd = Command::new(tool.path());
+ Sysroot::set_rustup_toolchain_env(&mut cmd, sysroot);
cmd.envs(extra_env);
cmd.arg("--version").current_dir(current_dir);
cmd
@@ -289,7 +290,8 @@ impl ProjectWorkspace {
let toolchain = get_toolchain_version(
cargo_toml.parent(),
- Sysroot::discover_tool(sysroot_ref, toolchain::Tool::Cargo),
+ sysroot_ref,
+ toolchain::Tool::Cargo,
&config.extra_env,
"cargo ",
)?;
@@ -370,9 +372,13 @@ impl ProjectWorkspace {
let sysroot_ref = sysroot.as_ref().ok();
let cfg_config = RustcCfgConfig::Rustc(sysroot_ref);
let data_layout_config = RustcDataLayoutConfig::Rustc(sysroot_ref);
- let rustc = Sysroot::discover_tool(sysroot_ref, toolchain::Tool::Rustc).map(Into::into);
- let toolchain = match get_toolchain_version(project_json.path(), rustc, extra_env, "rustc ")
- {
+ let toolchain = match get_toolchain_version(
+ project_json.path(),
+ sysroot_ref,
+ toolchain::Tool::Rustc,
+ extra_env,
+ "rustc ",
+ ) {
Ok(it) => it,
Err(e) => {
tracing::error!("{e}");
@@ -1615,10 +1621,8 @@ fn cargo_config_env(
extra_env: &FxHashMap<String, String>,
sysroot: Option<&Sysroot>,
) -> FxHashMap<String, String> {
- let Ok(program) = Sysroot::discover_tool(sysroot, toolchain::Tool::Cargo) else {
- return Default::default();
- };
- let mut cargo_config = Command::new(program);
+ let mut cargo_config = Command::new(Tool::Cargo.path());
+ Sysroot::set_rustup_toolchain_env(&mut cargo_config, sysroot);
cargo_config.envs(extra_env);
cargo_config
.current_dir(cargo_toml.parent())
diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs
index b175dbc895..1eb840afe5 100644
--- a/crates/rust-analyzer/src/handlers/request.rs
+++ b/crates/rust-analyzer/src/handlers/request.rs
@@ -1937,7 +1937,7 @@ fn run_rustfmt(
let mut command = match snap.config.rustfmt() {
RustfmtConfig::Rustfmt { extra_args, enable_range_formatting } => {
- // FIXME: This should use the sysroot's rustfmt if its loaded
+ // FIXME: Set RUSTUP_TOOLCHAIN
let mut cmd = process::Command::new(toolchain::rustfmt());
cmd.envs(snap.config.extra_env());
cmd.args(extra_args);
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index 93b6a53908..f223bb40c4 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -24,7 +24,7 @@ use ide_db::{
use itertools::Itertools;
use load_cargo::{load_proc_macro, ProjectFolders};
use proc_macro_api::ProcMacroServer;
-use project_model::{ProjectWorkspace, Sysroot, WorkspaceBuildScripts};
+use project_model::{ProjectWorkspace, WorkspaceBuildScripts};
use rustc_hash::FxHashSet;
use stdx::{format_to, thread::ThreadIntent};
use triomphe::Arc;
@@ -468,16 +468,20 @@ impl GlobalState {
None => ws.find_sysroot_proc_macro_srv()?,
};
- let env = match ws {
- ProjectWorkspace::Cargo { cargo_config_extra_env, .. } => {
- cargo_config_extra_env
- .iter()
- .chain(self.config.extra_env())
- .map(|(a, b)| (a.clone(), b.clone()))
- .collect()
- }
- _ => Default::default(),
- };
+ let env =
+ match ws {
+ ProjectWorkspace::Cargo { cargo_config_extra_env, sysroot, .. } => {
+ cargo_config_extra_env
+ .iter()
+ .chain(self.config.extra_env())
+ .map(|(a, b)| (a.clone(), b.clone()))
+ .chain(sysroot.as_ref().map(|it| {
+ ("RUSTUP_TOOLCHAIN".to_owned(), it.root().to_string())
+ }))
+ .collect()
+ }
+ _ => Default::default(),
+ };
tracing::info!("Using proc-macro server at {path}");
ProcMacroServer::spawn(path.clone(), &env).map_err(|err| {
@@ -620,7 +624,7 @@ impl GlobalState {
0,
Box::new(move |msg| sender.send(msg).unwrap()),
config,
- toolchain::cargo(),
+ None,
self.config.root_path().clone(),
)],
flycheck::InvocationStrategy::PerWorkspace => {
@@ -631,7 +635,7 @@ impl GlobalState {
ProjectWorkspace::Cargo { cargo, sysroot, .. } => Some((
id,
cargo.workspace_root(),
- Sysroot::discover_tool(sysroot.as_ref().ok(), toolchain::Tool::Cargo),
+ sysroot.as_ref().ok().map(|sysroot| sysroot.root().to_owned()),
)),
ProjectWorkspace::Json { project, sysroot, .. } => {
// Enable flychecks for json projects if a custom flycheck command was supplied
@@ -640,23 +644,20 @@ impl GlobalState {
FlycheckConfig::CustomCommand { .. } => Some((
id,
project.path(),
- Sysroot::discover_tool(
- sysroot.as_ref().ok(),
- toolchain::Tool::Cargo,
- ),
+ sysroot.as_ref().ok().map(|sysroot| sysroot.root().to_owned()),
)),
_ => None,
}
}
ProjectWorkspace::DetachedFiles { .. } => None,
})
- .map(|(id, root, cargo)| {
+ .map(|(id, root, sysroot_root)| {
let sender = sender.clone();
FlycheckHandle::spawn(
id,
Box::new(move |msg| sender.send(msg).unwrap()),
config.clone(),
- cargo.unwrap_or_else(|_| toolchain::cargo()),
+ sysroot_root,
root.to_path_buf(),
)
})