Skip to content

Commit e5b1a2b

Browse files
committed
Auto merge of rust-lang#17605 - Veykril:runnable-sysroot, r=Veykril
Set `RUSTC_TOOLCHAIN` for runnables With this the client doesn't necessarily need to guess the sysroot anymore
2 parents 064e6ed + 4f031d9 commit e5b1a2b

File tree

8 files changed

+59
-43
lines changed

8 files changed

+59
-43
lines changed

src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,7 @@ impl GlobalStateSnapshot {
579579
target_kind: target_data.kind,
580580
required_features: target_data.required_features.clone(),
581581
features: package_data.features.keys().cloned().collect(),
582+
sysroot_root: workspace.sysroot.root().map(ToOwned::to_owned),
582583
}));
583584
}
584585
ProjectWorkspaceKind::Json(project) => {

src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ use crate::{
5050
self, CrateInfoResult, ExternalDocsPair, ExternalDocsResponse, FetchDependencyListParams,
5151
FetchDependencyListResult, PositionOrRange, ViewCrateGraphParams, WorkspaceSymbolParams,
5252
},
53-
target_spec::TargetSpec,
53+
target_spec::{CargoTargetSpec, TargetSpec},
5454
};
5555

5656
pub(crate) fn handle_workspace_reload(state: &mut GlobalState, _: ()) -> anyhow::Result<()> {
@@ -848,6 +848,14 @@ pub(crate) fn handle_runnables(
848848
if let lsp_ext::RunnableArgs::Cargo(r) = &mut runnable.args {
849849
runnable.label = format!("{} + expect", runnable.label);
850850
r.environment.insert("UPDATE_EXPECT".to_owned(), "1".to_owned());
851+
if let Some(TargetSpec::Cargo(CargoTargetSpec {
852+
sysroot_root: Some(sysroot_root),
853+
..
854+
})) = &target_spec
855+
{
856+
r.environment
857+
.insert("RUSTC_TOOLCHAIN".to_owned(), sysroot_root.to_string());
858+
}
851859
}
852860
}
853861
res.push(runnable);
@@ -889,7 +897,12 @@ pub(crate) fn handle_runnables(
889897
override_cargo: config.override_cargo.clone(),
890898
cargo_args,
891899
executable_args: Vec::new(),
892-
environment: Default::default(),
900+
environment: spec
901+
.sysroot_root
902+
.as_ref()
903+
.map(|root| ("RUSTC_TOOLCHAIN".to_owned(), root.to_string()))
904+
.into_iter()
905+
.collect(),
893906
}),
894907
})
895908
}

src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1399,7 +1399,11 @@ pub(crate) fn runnable(
13991399
cargo_args,
14001400
cwd: cwd.into(),
14011401
executable_args,
1402-
environment: Default::default(),
1402+
environment: spec
1403+
.sysroot_root
1404+
.map(|root| ("RUSTC_TOOLCHAIN".to_owned(), root.to_string()))
1405+
.into_iter()
1406+
.collect(),
14031407
}),
14041408
}))
14051409
}

src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ pub(crate) struct CargoTargetSpec {
5757
pub(crate) crate_id: CrateId,
5858
pub(crate) required_features: Vec<String>,
5959
pub(crate) features: FxHashSet<String>,
60+
pub(crate) sysroot_root: Option<vfs::AbsPathBuf>,
6061
}
6162

6263
#[derive(Clone, Debug)]

src/tools/rust-analyzer/editors/code/src/debug.ts

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ import * as vscode from "vscode";
33
import * as path from "path";
44
import type * as ra from "./lsp_ext";
55

6-
import { Cargo, getRustcId, getSysroot } from "./toolchain";
6+
import { Cargo } from "./toolchain";
77
import type { Ctx } from "./ctx";
88
import { prepareEnv } from "./run";
9-
import { isCargoRunnableArgs, unwrapUndefinable } from "./util";
9+
import { execute, isCargoRunnableArgs, unwrapUndefinable } from "./util";
1010

1111
const debugOutput = vscode.window.createOutputChannel("Debug");
1212
type DebugConfigProvider = (
@@ -142,18 +142,29 @@ async function getDebugConfiguration(
142142
const executable = await getDebugExecutable(runnableArgs, env);
143143
let sourceFileMap = debugOptions.sourceFileMap;
144144
if (sourceFileMap === "auto") {
145-
// let's try to use the default toolchain
146-
const [commitHash, sysroot] = await Promise.all([
147-
getRustcId(wsFolder),
148-
getSysroot(wsFolder),
149-
]);
150-
const rustlib = path.normalize(sysroot + "/lib/rustlib/src/rust");
151145
sourceFileMap = {};
152-
sourceFileMap[`/rustc/${commitHash}/`] = rustlib;
146+
const sysroot = env["RUSTC_TOOLCHAIN"];
147+
if (sysroot) {
148+
// let's try to use the default toolchain
149+
const data = await execute(`rustc -V -v`, { cwd: wsFolder, env });
150+
const rx = /commit-hash:\s(.*)$/m;
151+
152+
const commitHash = rx.exec(data)?.[1];
153+
if (commitHash) {
154+
const rustlib = path.normalize(sysroot + "/lib/rustlib/src/rust");
155+
sourceFileMap[`/rustc/${commitHash}/`] = rustlib;
156+
}
157+
}
153158
}
154159

155160
const provider = unwrapUndefinable(knownEngines[debugEngine.id]);
156-
const debugConfig = provider(runnable, runnableArgs, simplifyPath(executable), env);
161+
const debugConfig = provider(
162+
runnable,
163+
runnableArgs,
164+
simplifyPath(executable),
165+
env,
166+
sourceFileMap,
167+
);
157168
if (debugConfig.type in debugOptions.engineSettings) {
158169
const settingsMap = (debugOptions.engineSettings as any)[debugConfig.type];
159170
for (var key in settingsMap) {

src/tools/rust-analyzer/editors/code/src/run.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { makeDebugConfig } from "./debug";
88
import type { Config, RunnableEnvCfg, RunnableEnvCfgItem } from "./config";
99
import type { LanguageClient } from "vscode-languageclient/node";
1010
import { unwrapUndefinable, type RustEditor } from "./util";
11-
import * as toolchain from "./toolchain";
1211

1312
const quickPickButtons = [
1413
{ iconPath: new vscode.ThemeIcon("save"), tooltip: "Save as a launch.json configuration." },
@@ -115,7 +114,7 @@ export async function createTaskFromRunnable(
115114

116115
let definition: tasks.TaskDefinition;
117116
let options;
118-
let cargo;
117+
let cargo = "cargo";
119118
if (runnable.kind === "cargo") {
120119
const runnableArgs = runnable.args;
121120
let args = createCargoArgs(runnableArgs);
@@ -126,8 +125,6 @@ export async function createTaskFromRunnable(
126125

127126
cargo = unwrapUndefinable(cargoParts[0]);
128127
args = [...cargoParts.slice(1), ...args];
129-
} else {
130-
cargo = await toolchain.cargoPath();
131128
}
132129

133130
definition = {
@@ -200,7 +197,7 @@ async function getRunnables(
200197
continue;
201198
}
202199

203-
if (debuggeeOnly && (r.label.startsWith("doctest") || r.label.startsWith("cargo"))) {
200+
if (debuggeeOnly && r.label.startsWith("doctest")) {
204201
continue;
205202
}
206203
items.push(new RunnableQuickPick(r));

src/tools/rust-analyzer/editors/code/src/tasks.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ export async function targetToExecution(
125125
let command, args;
126126
if (isCargoTask(definition)) {
127127
// FIXME: The server should provide cargo
128-
command = cargo || (await toolchain.cargoPath());
128+
command = cargo || (await toolchain.cargoPath(options?.env));
129129
args = [definition.command].concat(definition.args || []);
130130
} else {
131131
command = definition.command;

src/tools/rust-analyzer/editors/code/src/toolchain.ts

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as os from "os";
33
import * as path from "path";
44
import * as readline from "readline";
55
import * as vscode from "vscode";
6-
import { execute, log, memoizeAsync, unwrapNullable, unwrapUndefinable } from "./util";
6+
import { log, memoizeAsync, unwrapUndefinable } from "./util";
77
import type { CargoRunnableArgs } from "./lsp_ext";
88

99
interface CompilationArtifact {
@@ -55,7 +55,10 @@ export class Cargo {
5555
return result;
5656
}
5757

58-
private async getArtifacts(spec: ArtifactSpec): Promise<CompilationArtifact[]> {
58+
private async getArtifacts(
59+
spec: ArtifactSpec,
60+
env?: Record<string, string>,
61+
): Promise<CompilationArtifact[]> {
5962
const artifacts: CompilationArtifact[] = [];
6063

6164
try {
@@ -78,6 +81,7 @@ export class Cargo {
7881
}
7982
},
8083
(stderr) => this.output.append(stderr),
84+
env,
8185
);
8286
} catch (err) {
8387
this.output.show(true);
@@ -90,6 +94,7 @@ export class Cargo {
9094
async executableFromArgs(runnableArgs: CargoRunnableArgs): Promise<string> {
9195
const artifacts = await this.getArtifacts(
9296
Cargo.artifactSpec(runnableArgs.cargoArgs, runnableArgs.executableArgs),
97+
runnableArgs.environment,
9398
);
9499

95100
if (artifacts.length === 0) {
@@ -106,8 +111,9 @@ export class Cargo {
106111
cargoArgs: string[],
107112
onStdoutJson: (obj: any) => void,
108113
onStderrString: (data: string) => void,
114+
env?: Record<string, string>,
109115
): Promise<number> {
110-
const path = await cargoPath();
116+
const path = await cargoPath(env);
111117
return await new Promise((resolve, reject) => {
112118
const cargo = cp.spawn(path, cargoArgs, {
113119
stdio: ["ignore", "pipe", "pipe"],
@@ -133,29 +139,12 @@ export class Cargo {
133139
}
134140
}
135141

136-
/** Mirrors `project_model::sysroot::discover_sysroot_dir()` implementation*/
137-
export async function getSysroot(dir: string): Promise<string> {
138-
const rustcPath = await getPathForExecutable("rustc");
139-
140-
// do not memoize the result because the toolchain may change between runs
141-
return await execute(`${rustcPath} --print sysroot`, { cwd: dir });
142-
}
143-
144-
export async function getRustcId(dir: string): Promise<string> {
145-
const rustcPath = await getPathForExecutable("rustc");
146-
147-
// do not memoize the result because the toolchain may change between runs
148-
const data = await execute(`${rustcPath} -V -v`, { cwd: dir });
149-
const rx = /commit-hash:\s(.*)$/m;
150-
151-
const result = unwrapNullable(rx.exec(data));
152-
const first = unwrapUndefinable(result[1]);
153-
return first;
154-
}
155-
156142
/** Mirrors `toolchain::cargo()` implementation */
157143
// FIXME: The server should provide this
158-
export function cargoPath(): Promise<string> {
144+
export function cargoPath(env?: Record<string, string>): Promise<string> {
145+
if (env?.["RUSTC_TOOLCHAIN"]) {
146+
return Promise.resolve("cargo");
147+
}
159148
return getPathForExecutable("cargo");
160149
}
161150

0 commit comments

Comments
 (0)