Skip to content

Commit f573369

Browse files
committed
Fix [env] in .cargo/config.toml overriding process environment variables
cargo_config_env() only checked extra_env (rust-analyzer.cargo.extraEnv) when deciding whether to skip an existing variable, but never checked the actual process environment via std::env::var. This caused config.toml values to unconditionally override real environment variables even without force = true, diverging from Cargo's behavior. Additionally, plain string entries (e.g. `KEY = "value"`) skipped the force check entirely. When a process env var takes precedence, its value is now inserted into the Env so that env!/option_env! resolution stays correct. Fixes rust-lang/rust-analyzer#21994
1 parent 6cff92d commit f573369

1 file changed

Lines changed: 20 additions & 7 deletions

File tree

  • src/tools/rust-analyzer/crates/project-model/src

src/tools/rust-analyzer/crates/project-model/src/env.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,18 +79,31 @@ pub(crate) fn cargo_config_env(
7979
for (key, entry) in env_toml {
8080
let key = key.as_ref().as_ref();
8181
let value = match entry.as_ref() {
82-
DeValue::String(s) => String::from(s.clone()),
82+
DeValue::String(s) => {
83+
// Plain string entries have no `force` option, so they should not
84+
// override existing environment variables (matching Cargo behavior).
85+
if extra_env.get(key).is_some_and(Option::is_some) {
86+
continue;
87+
}
88+
if let Ok(val) = std::env::var(key) { val } else { String::from(s.clone()) }
89+
}
8390
DeValue::Table(entry) => {
8491
// Each entry MUST have a `value` key.
8592
let Some(map) = entry.get("value").and_then(|v| v.as_ref().as_str()) else {
8693
continue;
8794
};
88-
// If the entry already exists in the environment AND the `force` key is not set to
89-
// true, then don't overwrite the value.
90-
if extra_env.get(key).is_some_and(Option::is_some)
91-
&& !entry.get("force").and_then(|v| v.as_ref().as_bool()).unwrap_or(false)
92-
{
93-
continue;
95+
let is_forced =
96+
entry.get("force").and_then(|v| v.as_ref().as_bool()).unwrap_or(false);
97+
// If the entry already exists in the environment AND the `force` key is not set
98+
// to true, use the existing value instead of the config value.
99+
if !is_forced {
100+
if extra_env.get(key).is_some_and(Option::is_some) {
101+
continue;
102+
}
103+
if let Ok(val) = std::env::var(key) {
104+
env.insert(key, val);
105+
continue;
106+
}
94107
}
95108

96109
if let Some(base) = entry.get("relative").and_then(|v| {

0 commit comments

Comments
 (0)