From 64c17a9b2ebf72e5480538c287b35557a20fa3e8 Mon Sep 17 00:00:00 2001
From: Lukas Wirth <lukastw97@gmail.com>
Date: Tue, 27 Feb 2024 10:20:07 +0100
Subject: [PATCH] fix: rust-project.json projects not preferring sysroot rustc

---
 crates/project-model/src/build_scripts.rs      |  3 +--
 crates/project-model/src/cargo_workspace.rs    |  3 +--
 crates/project-model/src/rustc_cfg.rs          |  3 +--
 crates/project-model/src/sysroot.rs            | 13 +++++++++++++
 crates/project-model/src/target_data_layout.rs |  3 +--
 crates/project-model/src/workspace.rs          | 18 ++++++++----------
 6 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/crates/project-model/src/build_scripts.rs b/crates/project-model/src/build_scripts.rs
index 621b6ca3efa4..27a8db40a998 100644
--- a/crates/project-model/src/build_scripts.rs
+++ b/crates/project-model/src/build_scripts.rs
@@ -440,8 +440,7 @@ impl WorkspaceBuildScripts {
                 if let Ok(it) = utf8_stdout(cargo_config) {
                     return Ok(it);
                 }
-                let mut cmd = Command::new(Tool::Rustc.path());
-                Sysroot::set_rustup_toolchain_env(&mut cmd, sysroot);
+                let mut cmd = Sysroot::rustc(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 08d86fd7b0fe..609b1f67b57d 100644
--- a/crates/project-model/src/cargo_workspace.rs
+++ b/crates/project-model/src/cargo_workspace.rs
@@ -501,8 +501,7 @@ fn rustc_discover_host_triple(
     extra_env: &FxHashMap<String, String>,
     sysroot: Option<&Sysroot>,
 ) -> Option<String> {
-    let mut rustc = Command::new(Tool::Rustc.path());
-    Sysroot::set_rustup_toolchain_env(&mut rustc, sysroot);
+    let mut rustc = Sysroot::rustc(sysroot);
     rustc.envs(extra_env);
     rustc.current_dir(cargo_toml.parent()).arg("-vV");
     tracing::debug!("Discovering host platform by {:?}", rustc);
diff --git a/crates/project-model/src/rustc_cfg.rs b/crates/project-model/src/rustc_cfg.rs
index 1ad6e7255bf1..001296fb0002 100644
--- a/crates/project-model/src/rustc_cfg.rs
+++ b/crates/project-model/src/rustc_cfg.rs
@@ -90,8 +90,7 @@ fn get_rust_cfgs(
         RustcCfgConfig::Rustc(sysroot) => sysroot,
     };
 
-    let mut cmd = Command::new(toolchain::Tool::Rustc.path());
-    Sysroot::set_rustup_toolchain_env(&mut cmd, sysroot);
+    let mut cmd = Sysroot::rustc(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 07cfaba2d2ca..ea24393ed8a2 100644
--- a/crates/project-model/src/sysroot.rs
+++ b/crates/project-model/src/sysroot.rs
@@ -199,6 +199,19 @@ impl Sysroot {
         }
     }
 
+    /// Returns a `Command` that is configured to run `rustc` from the sysroot if it exists,
+    /// otherwise returns what [toolchain::Tool::Rustc] returns.
+    pub fn rustc(sysroot: Option<&Self>) -> Command {
+        let mut cmd = Command::new(match sysroot {
+            Some(sysroot) => {
+                toolchain::Tool::Rustc.path_in_or_discover(sysroot.root.join("bin").as_ref())
+            }
+            None => toolchain::Tool::Rustc.path(),
+        });
+        Self::set_rustup_toolchain_env(&mut cmd, sysroot);
+        cmd
+    }
+
     pub fn discover_proc_macro_srv(&self) -> anyhow::Result<AbsPathBuf> {
         ["libexec", "lib"]
             .into_iter()
diff --git a/crates/project-model/src/target_data_layout.rs b/crates/project-model/src/target_data_layout.rs
index 98917351c5e8..df77541762d9 100644
--- a/crates/project-model/src/target_data_layout.rs
+++ b/crates/project-model/src/target_data_layout.rs
@@ -57,8 +57,7 @@ pub fn get(
         RustcDataLayoutConfig::Rustc(sysroot) => sysroot,
     };
 
-    let mut cmd = Command::new(toolchain::Tool::Rustc.path());
-    Sysroot::set_rustup_toolchain_env(&mut cmd, sysroot);
+    let mut cmd = Sysroot::rustc(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 bcb5dcadb5b9..adf15d45fc62 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -172,14 +172,11 @@ impl fmt::Debug for ProjectWorkspace {
 
 fn get_toolchain_version(
     current_dir: &AbsPath,
-    sysroot: Option<&Sysroot>,
-    tool: Tool,
+    mut cmd: Command,
     extra_env: &FxHashMap<String, String>,
     prefix: &str,
 ) -> Result<Option<Version>, anyhow::Error> {
     let cargo_version = utf8_stdout({
-        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
@@ -300,8 +297,11 @@ impl ProjectWorkspace {
 
                 let toolchain = get_toolchain_version(
                     cargo_toml.parent(),
-                    sysroot_ref,
-                    toolchain::Tool::Cargo,
+                    {
+                        let mut cmd = Command::new(toolchain::Tool::Cargo.path());
+                        Sysroot::set_rustup_toolchain_env(&mut cmd, sysroot_ref);
+                        cmd
+                    },
                     &config.extra_env,
                     "cargo ",
                 )?;
@@ -386,8 +386,7 @@ impl ProjectWorkspace {
         let data_layout_config = RustcDataLayoutConfig::Rustc(sysroot_ref);
         let toolchain = match get_toolchain_version(
             project_json.path(),
-            sysroot_ref,
-            toolchain::Tool::Rustc,
+            Sysroot::rustc(sysroot_ref),
             extra_env,
             "rustc ",
         ) {
@@ -436,8 +435,7 @@ impl ProjectWorkspace {
         let sysroot_ref = sysroot.as_ref().ok();
         let toolchain = match get_toolchain_version(
             dir,
-            sysroot_ref,
-            toolchain::Tool::Rustc,
+            Sysroot::rustc(sysroot_ref),
             &config.extra_env,
             "rustc ",
         ) {