about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-07-16 11:49:27 +0000
committerbors <bors@rust-lang.org>2024-07-16 11:49:27 +0000
commite5b1a2b3cd1e3a53b939e81a3eef1f4da924eb0f (patch)
tree32777f5902970e2a095804a0bdc062150b15c345
parent064e6ed163b4b695bd669983b57ad74949e15026 (diff)
parent4f031d976812aba0105300b8f77f73835d97c530 (diff)
downloadrust-e5b1a2b3cd1e3a53b939e81a3eef1f4da924eb0f.tar.gz
rust-e5b1a2b3cd1e3a53b939e81a3eef1f4da924eb0f.zip
Auto merge of #17605 - Veykril:runnable-sysroot, r=Veykril
Set `RUSTC_TOOLCHAIN` for runnables

With this the client doesn't necessarily need to guess the sysroot anymore
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs1
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs17
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs6
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs1
-rw-r--r--src/tools/rust-analyzer/editors/code/src/debug.ts31
-rw-r--r--src/tools/rust-analyzer/editors/code/src/run.ts7
-rw-r--r--src/tools/rust-analyzer/editors/code/src/tasks.ts2
-rw-r--r--src/tools/rust-analyzer/editors/code/src/toolchain.ts37
8 files changed, 59 insertions, 43 deletions
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
index de4c9586dfd..1976e4de306 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
@@ -579,6 +579,7 @@ impl GlobalStateSnapshot {
                         target_kind: target_data.kind,
                         required_features: target_data.required_features.clone(),
                         features: package_data.features.keys().cloned().collect(),
+                        sysroot_root: workspace.sysroot.root().map(ToOwned::to_owned),
                     }));
                 }
                 ProjectWorkspaceKind::Json(project) => {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
index e19f7a4898b..89961431143 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
@@ -50,7 +50,7 @@ use crate::{
         self, CrateInfoResult, ExternalDocsPair, ExternalDocsResponse, FetchDependencyListParams,
         FetchDependencyListResult, PositionOrRange, ViewCrateGraphParams, WorkspaceSymbolParams,
     },
-    target_spec::TargetSpec,
+    target_spec::{CargoTargetSpec, TargetSpec},
 };
 
 pub(crate) fn handle_workspace_reload(state: &mut GlobalState, _: ()) -> anyhow::Result<()> {
@@ -848,6 +848,14 @@ pub(crate) fn handle_runnables(
                 if let lsp_ext::RunnableArgs::Cargo(r) = &mut runnable.args {
                     runnable.label = format!("{} + expect", runnable.label);
                     r.environment.insert("UPDATE_EXPECT".to_owned(), "1".to_owned());
+                    if let Some(TargetSpec::Cargo(CargoTargetSpec {
+                        sysroot_root: Some(sysroot_root),
+                        ..
+                    })) = &target_spec
+                    {
+                        r.environment
+                            .insert("RUSTC_TOOLCHAIN".to_owned(), sysroot_root.to_string());
+                    }
                 }
             }
             res.push(runnable);
@@ -889,7 +897,12 @@ pub(crate) fn handle_runnables(
                         override_cargo: config.override_cargo.clone(),
                         cargo_args,
                         executable_args: Vec::new(),
-                        environment: Default::default(),
+                        environment: spec
+                            .sysroot_root
+                            .as_ref()
+                            .map(|root| ("RUSTC_TOOLCHAIN".to_owned(), root.to_string()))
+                            .into_iter()
+                            .collect(),
                     }),
                 })
             }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
index 323926e435c..cb9b141002e 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
@@ -1399,7 +1399,11 @@ pub(crate) fn runnable(
                     cargo_args,
                     cwd: cwd.into(),
                     executable_args,
-                    environment: Default::default(),
+                    environment: spec
+                        .sysroot_root
+                        .map(|root| ("RUSTC_TOOLCHAIN".to_owned(), root.to_string()))
+                        .into_iter()
+                        .collect(),
                 }),
             }))
         }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs
index 045b9e4198a..162faa5619c 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs
@@ -57,6 +57,7 @@ pub(crate) struct CargoTargetSpec {
     pub(crate) crate_id: CrateId,
     pub(crate) required_features: Vec<String>,
     pub(crate) features: FxHashSet<String>,
+    pub(crate) sysroot_root: Option<vfs::AbsPathBuf>,
 }
 
 #[derive(Clone, Debug)]
diff --git a/src/tools/rust-analyzer/editors/code/src/debug.ts b/src/tools/rust-analyzer/editors/code/src/debug.ts
index f23e3680933..d9622b4a0d2 100644
--- a/src/tools/rust-analyzer/editors/code/src/debug.ts
+++ b/src/tools/rust-analyzer/editors/code/src/debug.ts
@@ -3,10 +3,10 @@ import * as vscode from "vscode";
 import * as path from "path";
 import type * as ra from "./lsp_ext";
 
-import { Cargo, getRustcId, getSysroot } from "./toolchain";
+import { Cargo } from "./toolchain";
 import type { Ctx } from "./ctx";
 import { prepareEnv } from "./run";
-import { isCargoRunnableArgs, unwrapUndefinable } from "./util";
+import { execute, isCargoRunnableArgs, unwrapUndefinable } from "./util";
 
 const debugOutput = vscode.window.createOutputChannel("Debug");
 type DebugConfigProvider = (
@@ -142,18 +142,29 @@ async function getDebugConfiguration(
     const executable = await getDebugExecutable(runnableArgs, env);
     let sourceFileMap = debugOptions.sourceFileMap;
     if (sourceFileMap === "auto") {
-        // let's try to use the default toolchain
-        const [commitHash, sysroot] = await Promise.all([
-            getRustcId(wsFolder),
-            getSysroot(wsFolder),
-        ]);
-        const rustlib = path.normalize(sysroot + "/lib/rustlib/src/rust");
         sourceFileMap = {};
-        sourceFileMap[`/rustc/${commitHash}/`] = rustlib;
+        const sysroot = env["RUSTC_TOOLCHAIN"];
+        if (sysroot) {
+            // let's try to use the default toolchain
+            const data = await execute(`rustc -V -v`, { cwd: wsFolder, env });
+            const rx = /commit-hash:\s(.*)$/m;
+
+            const commitHash = rx.exec(data)?.[1];
+            if (commitHash) {
+                const rustlib = path.normalize(sysroot + "/lib/rustlib/src/rust");
+                sourceFileMap[`/rustc/${commitHash}/`] = rustlib;
+            }
+        }
     }
 
     const provider = unwrapUndefinable(knownEngines[debugEngine.id]);
-    const debugConfig = provider(runnable, runnableArgs, simplifyPath(executable), env);
+    const debugConfig = provider(
+        runnable,
+        runnableArgs,
+        simplifyPath(executable),
+        env,
+        sourceFileMap,
+    );
     if (debugConfig.type in debugOptions.engineSettings) {
         const settingsMap = (debugOptions.engineSettings as any)[debugConfig.type];
         for (var key in settingsMap) {
diff --git a/src/tools/rust-analyzer/editors/code/src/run.ts b/src/tools/rust-analyzer/editors/code/src/run.ts
index 783bbc1607d..7179eb37447 100644
--- a/src/tools/rust-analyzer/editors/code/src/run.ts
+++ b/src/tools/rust-analyzer/editors/code/src/run.ts
@@ -8,7 +8,6 @@ import { makeDebugConfig } from "./debug";
 import type { Config, RunnableEnvCfg, RunnableEnvCfgItem } from "./config";
 import type { LanguageClient } from "vscode-languageclient/node";
 import { unwrapUndefinable, type RustEditor } from "./util";
-import * as toolchain from "./toolchain";
 
 const quickPickButtons = [
     { iconPath: new vscode.ThemeIcon("save"), tooltip: "Save as a launch.json configuration." },
@@ -115,7 +114,7 @@ export async function createTaskFromRunnable(
 
     let definition: tasks.TaskDefinition;
     let options;
-    let cargo;
+    let cargo = "cargo";
     if (runnable.kind === "cargo") {
         const runnableArgs = runnable.args;
         let args = createCargoArgs(runnableArgs);
@@ -126,8 +125,6 @@ export async function createTaskFromRunnable(
 
             cargo = unwrapUndefinable(cargoParts[0]);
             args = [...cargoParts.slice(1), ...args];
-        } else {
-            cargo = await toolchain.cargoPath();
         }
 
         definition = {
@@ -200,7 +197,7 @@ async function getRunnables(
             continue;
         }
 
-        if (debuggeeOnly && (r.label.startsWith("doctest") || r.label.startsWith("cargo"))) {
+        if (debuggeeOnly && r.label.startsWith("doctest")) {
             continue;
         }
         items.push(new RunnableQuickPick(r));
diff --git a/src/tools/rust-analyzer/editors/code/src/tasks.ts b/src/tools/rust-analyzer/editors/code/src/tasks.ts
index fac1cc6394f..730ec6d1e90 100644
--- a/src/tools/rust-analyzer/editors/code/src/tasks.ts
+++ b/src/tools/rust-analyzer/editors/code/src/tasks.ts
@@ -125,7 +125,7 @@ export async function targetToExecution(
     let command, args;
     if (isCargoTask(definition)) {
         // FIXME: The server should provide cargo
-        command = cargo || (await toolchain.cargoPath());
+        command = cargo || (await toolchain.cargoPath(options?.env));
         args = [definition.command].concat(definition.args || []);
     } else {
         command = definition.command;
diff --git a/src/tools/rust-analyzer/editors/code/src/toolchain.ts b/src/tools/rust-analyzer/editors/code/src/toolchain.ts
index 6a0b5c26d82..850a6a55616 100644
--- a/src/tools/rust-analyzer/editors/code/src/toolchain.ts
+++ b/src/tools/rust-analyzer/editors/code/src/toolchain.ts
@@ -3,7 +3,7 @@ import * as os from "os";
 import * as path from "path";
 import * as readline from "readline";
 import * as vscode from "vscode";
-import { execute, log, memoizeAsync, unwrapNullable, unwrapUndefinable } from "./util";
+import { log, memoizeAsync, unwrapUndefinable } from "./util";
 import type { CargoRunnableArgs } from "./lsp_ext";
 
 interface CompilationArtifact {
@@ -55,7 +55,10 @@ export class Cargo {
         return result;
     }
 
-    private async getArtifacts(spec: ArtifactSpec): Promise<CompilationArtifact[]> {
+    private async getArtifacts(
+        spec: ArtifactSpec,
+        env?: Record<string, string>,
+    ): Promise<CompilationArtifact[]> {
         const artifacts: CompilationArtifact[] = [];
 
         try {
@@ -78,6 +81,7 @@ export class Cargo {
                     }
                 },
                 (stderr) => this.output.append(stderr),
+                env,
             );
         } catch (err) {
             this.output.show(true);
@@ -90,6 +94,7 @@ export class Cargo {
     async executableFromArgs(runnableArgs: CargoRunnableArgs): Promise<string> {
         const artifacts = await this.getArtifacts(
             Cargo.artifactSpec(runnableArgs.cargoArgs, runnableArgs.executableArgs),
+            runnableArgs.environment,
         );
 
         if (artifacts.length === 0) {
@@ -106,8 +111,9 @@ export class Cargo {
         cargoArgs: string[],
         onStdoutJson: (obj: any) => void,
         onStderrString: (data: string) => void,
+        env?: Record<string, string>,
     ): Promise<number> {
-        const path = await cargoPath();
+        const path = await cargoPath(env);
         return await new Promise((resolve, reject) => {
             const cargo = cp.spawn(path, cargoArgs, {
                 stdio: ["ignore", "pipe", "pipe"],
@@ -133,29 +139,12 @@ export class Cargo {
     }
 }
 
-/** Mirrors `project_model::sysroot::discover_sysroot_dir()` implementation*/
-export async function getSysroot(dir: string): Promise<string> {
-    const rustcPath = await getPathForExecutable("rustc");
-
-    // do not memoize the result because the toolchain may change between runs
-    return await execute(`${rustcPath} --print sysroot`, { cwd: dir });
-}
-
-export async function getRustcId(dir: string): Promise<string> {
-    const rustcPath = await getPathForExecutable("rustc");
-
-    // do not memoize the result because the toolchain may change between runs
-    const data = await execute(`${rustcPath} -V -v`, { cwd: dir });
-    const rx = /commit-hash:\s(.*)$/m;
-
-    const result = unwrapNullable(rx.exec(data));
-    const first = unwrapUndefinable(result[1]);
-    return first;
-}
-
 /** Mirrors `toolchain::cargo()` implementation */
 // FIXME: The server should provide this
-export function cargoPath(): Promise<string> {
+export function cargoPath(env?: Record<string, string>): Promise<string> {
+    if (env?.["RUSTC_TOOLCHAIN"]) {
+        return Promise.resolve("cargo");
+    }
     return getPathForExecutable("cargo");
 }