Skip to content

Commit 3b964a7

Browse files
committed
allow using null to unset an environment variable
this makes three changes: - all callsites of `toolchain::command` are changed to use `command(path, extra_env)`, instead of manually adding the env after the fact. - all `map<str, str>` are changed to `map<str, option<str>>`. - `command` checks for None and calls `env_remove` if so. this caught several places where environment variables weren't being propagated: - when running `rustc --print=target-libdir` - when running `cargo rustc -- --print=target-spec-json` - when running the custom DiscoverLinkedProjects config. I *think* this is for use with non-cargo build systems, so I didn't change it.
1 parent a09a550 commit 3b964a7

File tree

19 files changed

+114
-91
lines changed

19 files changed

+114
-91
lines changed

Diff for: crates/load-cargo/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ pub fn load_workspace_at(
6666

6767
pub fn load_workspace(
6868
ws: ProjectWorkspace,
69-
extra_env: &FxHashMap<String, String>,
69+
extra_env: &FxHashMap<String, Option<String>>,
7070
load_config: &LoadCargoConfig,
7171
) -> anyhow::Result<(RootDatabase, vfs::Vfs, Option<ProcMacroClient>)> {
7272
let (sender, receiver) = unbounded();

Diff for: crates/proc-macro-api/src/lib.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,11 @@ impl fmt::Display for ServerError {
105105

106106
impl ProcMacroClient {
107107
/// Spawns an external process as the proc macro server and returns a client connected to it.
108-
pub fn spawn(
108+
pub fn spawn<'a>(
109109
process_path: &AbsPath,
110-
env: impl IntoIterator<Item = (impl AsRef<std::ffi::OsStr>, impl AsRef<std::ffi::OsStr>)>
111-
+ Clone,
110+
env: impl IntoIterator<
111+
Item = (impl AsRef<std::ffi::OsStr>, &'a Option<impl 'a + AsRef<std::ffi::OsStr>>),
112+
> + Clone,
112113
) -> io::Result<ProcMacroClient> {
113114
let process = ProcMacroServerProcess::run(process_path, env)?;
114115
Ok(ProcMacroClient { process: Arc::new(process), path: process_path.to_owned() })

Diff for: crates/proc-macro-api/src/process.rs

+19-9
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,11 @@ struct ProcessSrvState {
4343

4444
impl ProcMacroServerProcess {
4545
/// Starts the proc-macro server and performs a version check
46-
pub(crate) fn run(
46+
pub(crate) fn run<'a>(
4747
process_path: &AbsPath,
48-
env: impl IntoIterator<Item = (impl AsRef<std::ffi::OsStr>, impl AsRef<std::ffi::OsStr>)>
49-
+ Clone,
48+
env: impl IntoIterator<
49+
Item = (impl AsRef<std::ffi::OsStr>, &'a Option<impl 'a + AsRef<std::ffi::OsStr>>),
50+
> + Clone,
5051
) -> io::Result<ProcMacroServerProcess> {
5152
let create_srv = || {
5253
let mut process = Process::run(process_path, env.clone())?;
@@ -193,9 +194,11 @@ struct Process {
193194

194195
impl Process {
195196
/// Runs a new proc-macro server process with the specified environment variables.
196-
fn run(
197+
fn run<'a>(
197198
path: &AbsPath,
198-
env: impl IntoIterator<Item = (impl AsRef<std::ffi::OsStr>, impl AsRef<std::ffi::OsStr>)>,
199+
env: impl IntoIterator<
200+
Item = (impl AsRef<std::ffi::OsStr>, &'a Option<impl 'a + AsRef<std::ffi::OsStr>>),
201+
>,
199202
) -> io::Result<Process> {
200203
let child = JodChild(mk_child(path, env)?);
201204
Ok(Process { child })
@@ -212,14 +215,21 @@ impl Process {
212215
}
213216

214217
/// Creates and configures a new child process for the proc-macro server.
215-
fn mk_child(
218+
fn mk_child<'a>(
216219
path: &AbsPath,
217-
env: impl IntoIterator<Item = (impl AsRef<std::ffi::OsStr>, impl AsRef<std::ffi::OsStr>)>,
220+
extra_env: impl IntoIterator<
221+
Item = (impl AsRef<std::ffi::OsStr>, &'a Option<impl 'a + AsRef<std::ffi::OsStr>>),
222+
>,
218223
) -> io::Result<Child> {
219224
#[allow(clippy::disallowed_methods)]
220225
let mut cmd = Command::new(path);
221-
cmd.envs(env)
222-
.env("RUST_ANALYZER_INTERNALS_DO_NOT_USE", "this is unstable")
226+
for env in extra_env {
227+
match env {
228+
(key, Some(val)) => cmd.env(key, val),
229+
(key, None) => cmd.env_remove(key),
230+
};
231+
}
232+
cmd.env("RUST_ANALYZER_INTERNALS_DO_NOT_USE", "this is unstable")
223233
.stdin(Stdio::piped())
224234
.stdout(Stdio::piped())
225235
.stderr(Stdio::inherit());

Diff for: crates/project-model/src/build_dependencies.rs

+5-8
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ impl WorkspaceBuildScripts {
163163
pub(crate) fn rustc_crates(
164164
rustc: &CargoWorkspace,
165165
current_dir: &AbsPath,
166-
extra_env: &FxHashMap<String, String>,
166+
extra_env: &FxHashMap<String, Option<String>>,
167167
sysroot: &Sysroot,
168168
) -> Self {
169169
let mut bs = WorkspaceBuildScripts::default();
@@ -172,16 +172,14 @@ impl WorkspaceBuildScripts {
172172
}
173173
let res = (|| {
174174
let target_libdir = (|| {
175-
let mut cargo_config = sysroot.tool(Tool::Cargo, current_dir);
176-
cargo_config.envs(extra_env);
175+
let mut cargo_config = sysroot.tool(Tool::Cargo, current_dir, extra_env);
177176
cargo_config
178177
.args(["rustc", "-Z", "unstable-options", "--print", "target-libdir"])
179178
.env("RUSTC_BOOTSTRAP", "1");
180179
if let Ok(it) = utf8_stdout(&mut cargo_config) {
181180
return Ok(it);
182181
}
183-
let mut cmd = sysroot.tool(Tool::Rustc, current_dir);
184-
cmd.envs(extra_env);
182+
let mut cmd = sysroot.tool(Tool::Rustc, current_dir, extra_env);
185183
cmd.args(["--print", "target-libdir"]);
186184
utf8_stdout(&mut cmd)
187185
})()?;
@@ -390,12 +388,12 @@ impl WorkspaceBuildScripts {
390388
) -> io::Result<Command> {
391389
let mut cmd = match config.run_build_script_command.as_deref() {
392390
Some([program, args @ ..]) => {
393-
let mut cmd = toolchain::command(program, current_dir);
391+
let mut cmd = toolchain::command(program, current_dir, &config.extra_env);
394392
cmd.args(args);
395393
cmd
396394
}
397395
_ => {
398-
let mut cmd = sysroot.tool(Tool::Cargo, current_dir);
396+
let mut cmd = sysroot.tool(Tool::Cargo, current_dir, &config.extra_env);
399397

400398
cmd.args(["check", "--quiet", "--workspace", "--message-format=json"]);
401399
cmd.args(&config.extra_args);
@@ -448,7 +446,6 @@ impl WorkspaceBuildScripts {
448446
}
449447
};
450448

451-
cmd.envs(&config.extra_env);
452449
if config.wrap_rustc_in_build_scripts {
453450
// Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use
454451
// that to compile only proc macros and build scripts during the initial

Diff for: crates/project-model/src/cargo_workspace.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ pub struct CargoConfig {
104104
/// Extra args to pass to the cargo command.
105105
pub extra_args: Vec<String>,
106106
/// Extra env vars to set when invoking the cargo command
107-
pub extra_env: FxHashMap<String, String>,
107+
pub extra_env: FxHashMap<String, Option<String>>,
108108
pub invocation_strategy: InvocationStrategy,
109109
/// Optional path to use instead of `target` when building
110110
pub target_dir: Option<Utf8PathBuf>,
@@ -289,7 +289,7 @@ pub struct CargoMetadataConfig {
289289
/// Extra args to pass to the cargo command.
290290
pub extra_args: Vec<String>,
291291
/// Extra env vars to set when invoking the cargo command
292-
pub extra_env: FxHashMap<String, String>,
292+
pub extra_env: FxHashMap<String, Option<String>>,
293293
}
294294

295295
// Deserialize helper for the cargo metadata
@@ -343,11 +343,10 @@ impl CargoWorkspace {
343343
locked: bool,
344344
progress: &dyn Fn(String),
345345
) -> anyhow::Result<(cargo_metadata::Metadata, Option<anyhow::Error>)> {
346-
let cargo = sysroot.tool(Tool::Cargo, current_dir);
346+
let cargo = sysroot.tool(Tool::Cargo, current_dir, &config.extra_env);
347347
let mut meta = MetadataCommand::new();
348348
meta.cargo_path(cargo.get_program());
349349
cargo.get_envs().for_each(|(var, val)| _ = meta.env(var, val.unwrap_or_default()));
350-
config.extra_env.iter().for_each(|(var, val)| _ = meta.env(var, val));
351350
meta.manifest_path(cargo_toml.to_path_buf());
352351
match &config.features {
353352
CargoFeatures::All => {

Diff for: crates/project-model/src/env.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,10 @@ pub(crate) fn inject_rustc_tool_env(env: &mut Env, cargo_name: &str, kind: Targe
6262

6363
pub(crate) fn cargo_config_env(
6464
manifest: &ManifestPath,
65-
extra_env: &FxHashMap<String, String>,
65+
extra_env: &FxHashMap<String, Option<String>>,
6666
sysroot: &Sysroot,
6767
) -> Env {
68-
let mut cargo_config = sysroot.tool(Tool::Cargo, manifest.parent());
69-
cargo_config.envs(extra_env);
68+
let mut cargo_config = sysroot.tool(Tool::Cargo, manifest.parent(), extra_env);
7069
cargo_config
7170
.args(["-Z", "unstable-options", "config", "get", "env"])
7271
.env("RUSTC_BOOTSTRAP", "1");

Diff for: crates/project-model/src/sysroot.rs

+16-13
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ impl Sysroot {
8686

8787
impl Sysroot {
8888
/// Attempts to discover the toolchain's sysroot from the given `dir`.
89-
pub fn discover(dir: &AbsPath, extra_env: &FxHashMap<String, String>) -> Sysroot {
89+
pub fn discover(dir: &AbsPath, extra_env: &FxHashMap<String, Option<String>>) -> Sysroot {
9090
let sysroot_dir = discover_sysroot_dir(dir, extra_env);
9191
let rust_lib_src_dir = sysroot_dir.as_ref().ok().map(|sysroot_dir| {
9292
discover_rust_lib_src_dir_or_add_component(sysroot_dir, dir, extra_env)
@@ -96,7 +96,7 @@ impl Sysroot {
9696

9797
pub fn discover_with_src_override(
9898
current_dir: &AbsPath,
99-
extra_env: &FxHashMap<String, String>,
99+
extra_env: &FxHashMap<String, Option<String>>,
100100
rust_lib_src_dir: AbsPathBuf,
101101
) -> Sysroot {
102102
let sysroot_dir = discover_sysroot_dir(current_dir, extra_env);
@@ -118,7 +118,12 @@ impl Sysroot {
118118
}
119119

120120
/// Returns a command to run a tool preferring the cargo proxies if the sysroot exists.
121-
pub fn tool(&self, tool: Tool, current_dir: impl AsRef<Path>) -> Command {
121+
pub fn tool(
122+
&self,
123+
tool: Tool,
124+
current_dir: impl AsRef<Path>,
125+
envs: &FxHashMap<String, Option<String>>,
126+
) -> Command {
122127
match self.root() {
123128
Some(root) => {
124129
// special case rustc, we can look that up directly in the sysroot's bin folder
@@ -127,15 +132,15 @@ impl Sysroot {
127132
if let Some(path) =
128133
probe_for_binary(root.join("bin").join(Tool::Rustc.name()).into())
129134
{
130-
return toolchain::command(path, current_dir);
135+
return toolchain::command(path, current_dir, envs);
131136
}
132137
}
133138

134-
let mut cmd = toolchain::command(tool.prefer_proxy(), current_dir);
139+
let mut cmd = toolchain::command(tool.prefer_proxy(), current_dir, envs);
135140
cmd.env("RUSTUP_TOOLCHAIN", AsRef::<std::path::Path>::as_ref(root));
136141
cmd
137142
}
138-
_ => toolchain::command(tool.path(), current_dir),
143+
_ => toolchain::command(tool.path(), current_dir, envs),
139144
}
140145
}
141146

@@ -292,7 +297,7 @@ impl Sysroot {
292297
// the sysroot uses `public-dependency`, so we make cargo think it's a nightly
293298
cargo_config.extra_env.insert(
294299
"__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS".to_owned(),
295-
"nightly".to_owned(),
300+
Some("nightly".to_owned()),
296301
);
297302

298303
let (mut res, _) = match CargoWorkspace::fetch_metadata(
@@ -368,10 +373,9 @@ impl Sysroot {
368373

369374
fn discover_sysroot_dir(
370375
current_dir: &AbsPath,
371-
extra_env: &FxHashMap<String, String>,
376+
extra_env: &FxHashMap<String, Option<String>>,
372377
) -> Result<AbsPathBuf> {
373-
let mut rustc = toolchain::command(Tool::Rustc.path(), current_dir);
374-
rustc.envs(extra_env);
378+
let mut rustc = toolchain::command(Tool::Rustc.path(), current_dir, extra_env);
375379
rustc.current_dir(current_dir).args(["--print", "sysroot"]);
376380
tracing::debug!("Discovering sysroot by {:?}", rustc);
377381
let stdout = utf8_stdout(&mut rustc)?;
@@ -398,12 +402,11 @@ fn discover_rust_lib_src_dir(sysroot_path: &AbsPathBuf) -> Option<AbsPathBuf> {
398402
fn discover_rust_lib_src_dir_or_add_component(
399403
sysroot_path: &AbsPathBuf,
400404
current_dir: &AbsPath,
401-
extra_env: &FxHashMap<String, String>,
405+
extra_env: &FxHashMap<String, Option<String>>,
402406
) -> Result<AbsPathBuf> {
403407
discover_rust_lib_src_dir(sysroot_path)
404408
.or_else(|| {
405-
let mut rustup = toolchain::command(Tool::Rustup.prefer_proxy(), current_dir);
406-
rustup.envs(extra_env);
409+
let mut rustup = toolchain::command(Tool::Rustup.prefer_proxy(), current_dir, extra_env);
407410
rustup.args(["component", "add", "rust-src"]);
408411
tracing::info!("adding rust-src component by {:?}", rustup);
409412
utf8_stdout(&mut rustup).ok()?;

Diff for: crates/project-model/src/toolchain_info/rustc_cfg.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::{toolchain_info::QueryConfig, utf8_stdout};
1111
pub fn get(
1212
config: QueryConfig<'_>,
1313
target: Option<&str>,
14-
extra_env: &FxHashMap<String, String>,
14+
extra_env: &FxHashMap<String, Option<String>>,
1515
) -> Vec<CfgAtom> {
1616
let _p = tracing::info_span!("rustc_cfg::get").entered();
1717

@@ -58,14 +58,13 @@ pub fn get(
5858

5959
fn rustc_print_cfg(
6060
target: Option<&str>,
61-
extra_env: &FxHashMap<String, String>,
61+
extra_env: &FxHashMap<String, Option<String>>,
6262
config: QueryConfig<'_>,
6363
) -> anyhow::Result<String> {
6464
const RUSTC_ARGS: [&str; 2] = ["--print", "cfg"];
6565
let (sysroot, current_dir) = match config {
6666
QueryConfig::Cargo(sysroot, cargo_toml) => {
67-
let mut cmd = sysroot.tool(Tool::Cargo, cargo_toml.parent());
68-
cmd.envs(extra_env);
67+
let mut cmd = sysroot.tool(Tool::Cargo, cargo_toml.parent(), extra_env);
6968
cmd.args(["rustc", "-Z", "unstable-options"]).args(RUSTC_ARGS);
7069
if let Some(target) = target {
7170
cmd.args(["--target", target]);
@@ -86,8 +85,7 @@ fn rustc_print_cfg(
8685
QueryConfig::Rustc(sysroot, current_dir) => (sysroot, current_dir),
8786
};
8887

89-
let mut cmd = sysroot.tool(Tool::Rustc, current_dir);
90-
cmd.envs(extra_env);
88+
let mut cmd = sysroot.tool(Tool::Rustc, current_dir, extra_env);
9189
cmd.args(RUSTC_ARGS);
9290
cmd.arg("-O");
9391
if let Some(target) = target {

Diff for: crates/project-model/src/toolchain_info/target_data_layout.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{Sysroot, toolchain_info::QueryConfig, utf8_stdout};
1010
pub fn get(
1111
config: QueryConfig<'_>,
1212
target: Option<&str>,
13-
extra_env: &FxHashMap<String, String>,
13+
extra_env: &FxHashMap<String, Option<String>>,
1414
) -> anyhow::Result<String> {
1515
const RUSTC_ARGS: [&str; 2] = ["--print", "target-spec-json"];
1616
let process = |output: String| {
@@ -21,8 +21,7 @@ pub fn get(
2121
};
2222
let (sysroot, current_dir) = match config {
2323
QueryConfig::Cargo(sysroot, cargo_toml) => {
24-
let mut cmd = sysroot.tool(Tool::Cargo, cargo_toml.parent());
25-
cmd.envs(extra_env);
24+
let mut cmd = sysroot.tool(Tool::Cargo, cargo_toml.parent(), extra_env);
2625
cmd.env("RUSTC_BOOTSTRAP", "1");
2726
cmd.args(["rustc", "-Z", "unstable-options"]).args(RUSTC_ARGS).args([
2827
"--",
@@ -43,11 +42,8 @@ pub fn get(
4342
QueryConfig::Rustc(sysroot, current_dir) => (sysroot, current_dir),
4443
};
4544

46-
let mut cmd = Sysroot::tool(sysroot, Tool::Rustc, current_dir);
47-
cmd.envs(extra_env)
48-
.env("RUSTC_BOOTSTRAP", "1")
49-
.args(["-Z", "unstable-options"])
50-
.args(RUSTC_ARGS);
45+
let mut cmd = Sysroot::tool(sysroot, Tool::Rustc, current_dir, extra_env);
46+
cmd.env("RUSTC_BOOTSTRAP", "1").args(["-Z", "unstable-options"]).args(RUSTC_ARGS);
5147
if let Some(target) = target {
5248
cmd.args(["--target", target]);
5349
}

Diff for: crates/project-model/src/toolchain_info/target_tuple.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::{ManifestPath, Sysroot, toolchain_info::QueryConfig, utf8_stdout};
1212
pub fn get(
1313
config: QueryConfig<'_>,
1414
target: Option<&str>,
15-
extra_env: &FxHashMap<String, String>,
15+
extra_env: &FxHashMap<String, Option<String>>,
1616
) -> anyhow::Result<Vec<String>> {
1717
let _p = tracing::info_span!("target_tuple::get").entered();
1818
if let Some(target) = target {
@@ -32,12 +32,11 @@ pub fn get(
3232
}
3333

3434
fn rustc_discover_host_tuple(
35-
extra_env: &FxHashMap<String, String>,
35+
extra_env: &FxHashMap<String, Option<String>>,
3636
sysroot: &Sysroot,
3737
current_dir: &Path,
3838
) -> anyhow::Result<String> {
39-
let mut cmd = sysroot.tool(Tool::Rustc, current_dir);
40-
cmd.envs(extra_env);
39+
let mut cmd = sysroot.tool(Tool::Rustc, current_dir, extra_env);
4140
cmd.arg("-vV");
4241
let stdout = utf8_stdout(&mut cmd)
4342
.with_context(|| format!("unable to discover host platform via `{cmd:?}`"))?;
@@ -53,11 +52,10 @@ fn rustc_discover_host_tuple(
5352

5453
fn cargo_config_build_target(
5554
cargo_toml: &ManifestPath,
56-
extra_env: &FxHashMap<String, String>,
55+
extra_env: &FxHashMap<String, Option<String>>,
5756
sysroot: &Sysroot,
5857
) -> Option<Vec<String>> {
59-
let mut cmd = sysroot.tool(Tool::Cargo, cargo_toml.parent());
60-
cmd.envs(extra_env);
58+
let mut cmd = sysroot.tool(Tool::Cargo, cargo_toml.parent(), extra_env);
6159
cmd.current_dir(cargo_toml.parent()).env("RUSTC_BOOTSTRAP", "1");
6260
cmd.args(["-Z", "unstable-options", "config", "get", "build.target"]);
6361
// if successful we receive `build.target = "target-tuple"`

Diff for: crates/project-model/src/toolchain_info/version.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,16 @@ use crate::{toolchain_info::QueryConfig, utf8_stdout};
99

1010
pub(crate) fn get(
1111
config: QueryConfig<'_>,
12-
extra_env: &FxHashMap<String, String>,
12+
extra_env: &FxHashMap<String, Option<String>>,
1313
) -> Result<Option<Version>, anyhow::Error> {
1414
let (mut cmd, prefix) = match config {
1515
QueryConfig::Cargo(sysroot, cargo_toml) => {
16-
(sysroot.tool(Tool::Cargo, cargo_toml.parent()), "cargo ")
16+
(sysroot.tool(Tool::Cargo, cargo_toml.parent(), extra_env), "cargo ")
1717
}
1818
QueryConfig::Rustc(sysroot, current_dir) => {
19-
(sysroot.tool(Tool::Rustc, current_dir), "rustc ")
19+
(sysroot.tool(Tool::Rustc, current_dir, extra_env), "rustc ")
2020
}
2121
};
22-
cmd.envs(extra_env);
2322
cmd.arg("--version");
2423
let out = utf8_stdout(&mut cmd).with_context(|| format!("Failed to query rust toolchain version via `{cmd:?}`, is your toolchain setup correctly?"))?;
2524

0 commit comments

Comments
 (0)