@@ -217,7 +217,7 @@ impl<'a> Toolchain<'a> {
217217 new_path. push ( PathBuf :: from ( "/usr/lib" ) ) ;
218218 }
219219
220- env_var:: prepend_path ( sysenv:: LOADER_PATH , new_path, cmd, self . cfg . process ) ;
220+ env_var:: insert_path ( sysenv:: LOADER_PATH , new_path, None , cmd, self . cfg . process ) ;
221221
222222 // Prepend CARGO_HOME/bin to the PATH variable so that we're sure to run
223223 // cargo/rustc via the proxy bins. There is no fallback case for if the
@@ -228,30 +228,50 @@ impl<'a> Toolchain<'a> {
228228 path_entries. push ( cargo_home. join ( "bin" ) ) ;
229229 }
230230
231- // Historically rustup included the bin directory in PATH to
232- // work around some bugs (see
233- // https://github.com/rust-lang/rustup/pull/3178 for more
234- // information). This shouldn't be needed anymore, and it causes
231+ // On Windows, we append the "bin" directory to PATH by default.
232+ // Windows loads DLLs from PATH and the "bin" directory contains DLLs
233+ // that proc macros and other tools not in the sysroot use.
234+ // It's appended rather than prepended so that the exe files in "bin"
235+ // do not take precedence over anything else in PATH.
236+ //
237+ // Historically rustup prepended the bin directory in PATH but doing so causes
235238 // problems because calling tools recursively (like `cargo
236239 // +nightly metadata` from within a cargo subcommand). The
237240 // recursive call won't work because it is not executing the
238241 // proxy, so the `+` toolchain override doesn't work.
242+ // See: https://github.com/rust-lang/rustup/pull/3178
239243 //
240- // The RUSTUP_WINDOWS_PATH_ADD_BIN env var was added to opt-in to
241- // testing the fix. The default is now off, but this is left here
242- // just in case there are problems. Consider removing in the
243- // future if it doesn't seem necessary.
244- #[ cfg( target_os = "windows" ) ]
245- if self
246- . cfg
247- . process
248- . var_os ( "RUSTUP_WINDOWS_PATH_ADD_BIN" )
249- . is_some_and ( |s| s == "1" )
250- {
251- path_entries. push ( self . path . join ( "bin" ) ) ;
252- }
244+ // This behaviour was then changed to not add the bin directory at all.
245+ // But this caused another set of problems due to the sysroot DLLs
246+ // not being found by the loader, e.g. for proc macros.
247+ // See: https://github.com/rust-lang/rustup/issues/3825
248+ //
249+ // Which is how we arrived at the current default described above.
250+ //
251+ // The `RUSTUP_WINDOWS_PATH_ADD_BIN` environment variable allows
252+ // users to opt-in to one of the old behaviours in case the new
253+ // default causes any new issues.
254+ //
255+ // FIXME: The `RUSTUP_WINDOWS_PATH_ADD_BIN` environment variable can
256+ // be removed once we're confident that the default behaviour works.
257+ let append = if cfg ! ( target_os = "windows" ) {
258+ let add_bin = self . cfg . process . var ( "RUSTUP_WINDOWS_PATH_ADD_BIN" ) ;
259+ match add_bin. as_deref ( ) . unwrap_or ( "2" ) {
260+ // Don't add to PATH at all
261+ "0" => None ,
262+ // Prepend to PATH
263+ "1" => {
264+ path_entries. push ( self . path . join ( "bin" ) ) ;
265+ None
266+ }
267+ // Append to PATH (the default)
268+ _ => Some ( self . path . join ( "bin" ) ) ,
269+ }
270+ } else {
271+ None
272+ } ;
253273
254- env_var:: prepend_path ( "PATH" , path_entries, cmd, self . cfg . process ) ;
274+ env_var:: insert_path ( "PATH" , path_entries, append , cmd, self . cfg . process ) ;
255275 }
256276
257277 /// Infallible function that describes the version of rustc in an installed distribution
0 commit comments