diff --git a/src/bin/cargo/main.rs b/src/bin/cargo/main.rs index a29b77b3cdfc..797fb7464be8 100644 --- a/src/bin/cargo/main.rs +++ b/src/bin/cargo/main.rs @@ -220,10 +220,30 @@ fn is_executable>(path: P) -> bool { } fn search_directories(config: &Config) -> Vec { - let mut dirs = vec![config.home().clone().into_path_unlocked().join("bin")]; - if let Some(val) = env::var_os("PATH") { - dirs.extend(env::split_paths(&val)); - } + let path_dirs = if let Some(val) = env::var_os("PATH") { + env::split_paths(&val).collect() + } else { + vec![] + }; + + let home_bin = config.home().clone().into_path_unlocked().join("bin"); + + // If any of that PATH elements contains `home_bin`, do not + // add it again. This is so that the users can control priority + // of it using PATH, while preserving the historical + // behavior of preferring it over system global directories even + // when not in PATH at all. + // See https://github.com/rust-lang/cargo/issues/11020 for details. + // + // Note: `p == home_bin` will ignore trailing paths, but we don't + // `canonicalize` the paths. + let mut dirs = if path_dirs.iter().any(|p| p == &home_bin) { + vec![] + } else { + vec![home_bin] + }; + + dirs.extend(path_dirs); dirs }