diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 8e9e2ac214d..83c918a0332 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -694,6 +694,11 @@ fn prepare_rustc(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> CargoResult base.inherit_jobserver(&build_runner.jobserver); build_deps_args(&mut base, build_runner, unit)?; add_cap_lints(build_runner.bcx, unit, &mut base); + if cargo_rustc_higher_args_precedence(build_runner) { + if let Some(args) = build_runner.bcx.extra_args_for(unit) { + base.args(args); + } + } base.args(&unit.rustflags); if build_runner.bcx.gctx.cli_unstable().binary_dep_depinfo { base.arg("-Z").arg("binary-dep-depinfo"); @@ -753,8 +758,11 @@ fn prepare_rustdoc(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> CargoResu } rustdoc.args(unit.pkg.manifest().lint_rustflags()); - if let Some(args) = build_runner.bcx.extra_args_for(unit) { - rustdoc.args(args); + + if !cargo_rustc_higher_args_precedence(build_runner) { + if let Some(args) = build_runner.bcx.extra_args_for(unit) { + rustdoc.args(args); + } } let metadata = build_runner.metadata_for_doc_units[unit]; @@ -795,6 +803,11 @@ fn prepare_rustdoc(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> CargoResu rustdoc::add_output_format(build_runner, unit, &mut rustdoc)?; + if cargo_rustc_higher_args_precedence(build_runner) { + if let Some(args) = build_runner.bcx.extra_args_for(unit) { + rustdoc.args(args); + } + } rustdoc.args(&unit.rustdocflags); if !crate_version_flag_already_present(&rustdoc) { @@ -1097,8 +1110,10 @@ fn build_base_args( cmd.args(unit.pkg.manifest().lint_rustflags()); cmd.args(&profile_rustflags); - if let Some(args) = build_runner.bcx.extra_args_for(unit) { - cmd.args(args); + if !cargo_rustc_higher_args_precedence(build_runner) { + if let Some(args) = build_runner.bcx.extra_args_for(unit) { + cmd.args(args); + } } // `-C overflow-checks` is implied by the setting of `-C debug-assertions`, @@ -1969,3 +1984,19 @@ fn scrape_output_path(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> CargoR .outputs(unit) .map(|outputs| outputs[0].path.clone()) } + +/// Provides a way to change the precedence of `cargo rustc -- `. +/// +/// This is intended to be a short-live function. +/// +/// See +fn cargo_rustc_higher_args_precedence(build_runner: &BuildRunner<'_, '_>) -> bool { + build_runner.bcx.gctx.nightly_features_allowed + && build_runner + .bcx + .gctx + .get_env("__CARGO_RUSTC_ORIG_ARGS_PRIO") + .ok() + .as_deref() + != Some("1") +} diff --git a/tests/testsuite/rustc.rs b/tests/testsuite/rustc.rs index be01f14650e..71ca898ae16 100644 --- a/tests/testsuite/rustc.rs +++ b/tests/testsuite/rustc.rs @@ -795,3 +795,66 @@ windows ) .run(); } + +#[cargo_test] +fn precedence() { + // Ensure that the precedence of cargo-rustc is only lower than RUSTFLAGS, + // but higher than most flags set by cargo. + // + // See rust-lang/cargo#14346 + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + edition = "2021" + + [lints.rust] + unexpected_cfgs = "allow" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("rustc --release -v -- --cfg cargo_rustc -C strip=symbols") + .env("RUSTFLAGS", "--cfg from_rustflags") + .masquerade_as_nightly_cargo(&["cargo-rustc-precedence"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc [..]-C strip=debuginfo [..]--cfg cargo_rustc -C strip=symbols --cfg from_rustflags` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Ensure the short-live env var to work + p.cargo("clean").run(); + p.cargo("rustc --release -v -- --cfg cargo_rustc -C strip=symbols") + .env("RUSTFLAGS", "--cfg from_rustflags") + .env("__CARGO_RUSTC_ORIG_ARGS_PRIO", "1") + .masquerade_as_nightly_cargo(&["cargo-rustc-precedence"]) + .with_stderr_data( + str![[r#" +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc [..]--cfg cargo_rustc -C strip=symbols [..]-C strip=debuginfo [..]--cfg from_rustflags` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]] + ) + .run(); + + // Ensure non-nightly to work as before + p.cargo("clean").run(); + p.cargo("rustc --release -v -- --cfg cargo_rustc -C strip=symbols") + .env("RUSTFLAGS", "--cfg from_rustflags") + .with_stderr_data( + str![[r#" +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc [..]--cfg cargo_rustc -C strip=symbols [..]-C strip=debuginfo [..]--cfg from_rustflags` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]] + ) + .run(); +}