diff --git a/src/cargo/core/compiler/build_context/target_info.rs b/src/cargo/core/compiler/build_context/target_info.rs index 784773fede23..170bd8769a31 100644 --- a/src/cargo/core/compiler/build_context/target_info.rs +++ b/src/cargo/core/compiler/build_context/target_info.rs @@ -364,6 +364,45 @@ impl TargetInfo { true } + /// The [`CheckCfg`] settings with extra arguments passed. + pub fn check_cfg_with_extra_args( + &self, + gctx: &GlobalContext, + rustc: &Rustc, + extra_args: &[String], + ) -> CargoResult { + let mut process = rustc.workspace_process(); + + apply_env_config(gctx, &mut process)?; + process + .arg("-") + .arg("--print=check-cfg") + .arg("--check-cfg=cfg()") + .arg("-Zunstable-options") + .args(&self.rustflags) + .args(extra_args) + .env_remove("RUSTC_LOG"); + + // Removes `FD_CLOEXEC` set by `jobserver::Client` to pass jobserver + // as environment variables specify. + if let Some(client) = gctx.jobserver_from_env() { + process.inherit_jobserver(client); + } + + let (output, _error) = rustc + .cached_output(&process, 0) + .with_context(|| "failed to run `rustc` to learn about check-cfg information")?; + + let lines = output.lines(); + let mut check_cfg = CheckCfg::default(); + check_cfg.exhaustive = true; + + Ok(lines.fold(check_cfg, |mut check_cfg, line| { + check_cfg.process_line(line); + check_cfg + })) + } + /// All the target [`Cfg`] settings. pub fn cfg(&self) -> &[Cfg] { &self.cfg diff --git a/src/cargo/util/lints.rs b/src/cargo/util/lints.rs index 40b7c4322447..1567c178b33b 100644 --- a/src/cargo/util/lints.rs +++ b/src/cargo/util/lints.rs @@ -976,6 +976,20 @@ pub fn unexpected_target_cfgs( return Ok(()); }; + // If we have extra `--check-cfg` args comming from the lints config, we need to + // refetch the `--print=check-cfg` with those extra args. + let lint_rustflags = pkg.manifest().lint_rustflags(); + let check_cfg = if lint_rustflags.iter().any(|a| a == "--check-cfg") { + Some(target_info.check_cfg_with_extra_args(gctx, &rustc, lint_rustflags)?) + } else { + None + }; + let check_cfg = check_cfg.as_ref().unwrap_or(&global_check_cfg); + + if !check_cfg.exhaustive { + return Ok(()); + } + for dep in pkg.summary().dependencies() { let Some(platform) = dep.platform() else { continue; @@ -984,16 +998,9 @@ pub fn unexpected_target_cfgs( continue; }; - // FIXME: If the `[lints.rust.unexpected_cfgs.check-cfg]` config is set we should - // re-fetch the check-cfg informations with those extra args - - if !global_check_cfg.exhaustive { - continue; - } - warn_on_unexpected_cfgs( gctx, - &global_check_cfg, + &check_cfg, cfg_expr, lint_level, error_count, diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md index d550ada3ec77..182ad97572e4 100644 --- a/src/doc/src/reference/unstable.md +++ b/src/doc/src/reference/unstable.md @@ -1735,8 +1735,6 @@ When in doubt, you can discuss this in [#14520](https://github.com/rust-lang/car * Tracking Issue: [#00000](https://github.com/rust-lang/cargo/issues/00000) -**WARNING: Incomplete/WIP!** - This feature checks for unexpected cfgs in `[target.'cfg(...)']` entries, based on `rustc --print=check-cfg`. diff --git a/tests/testsuite/cfg.rs b/tests/testsuite/cfg.rs index f057571de18d..309f4cd6b15b 100644 --- a/tests/testsuite/cfg.rs +++ b/tests/testsuite/cfg.rs @@ -620,11 +620,8 @@ fn unexpected_cfgs_target_with_lint() { p.cargo("check -Zcargo-lints -Zcheck-target-cfgs") .masquerade_as_nightly_cargo(&["requires -Zcheck-target-cfgs"]) - // FIXME: We should not warn on `cfg(foo = "foo")` but we currently do .with_stderr_data(str![[r#" [WARNING] [ROOT]/foo/Cargo.toml: unexpected `cfg` condition name: `bar` in `[target.'cfg(bar)'.dependencies]` -[WARNING] [ROOT]/foo/Cargo.toml: unexpected `cfg` condition name: `foo` for `foo = "foo"` in `[target.'cfg(foo = "foo")'.dependencies]` -[WARNING] [ROOT]/foo/Cargo.toml: unexpected `cfg` condition name: `foo` in `[target.'cfg(foo)'.dependencies]` [LOCKING] 1 package to latest compatible version [CHECKING] a v0.0.1 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s @@ -729,13 +726,12 @@ fn unexpected_cfgs_target_cfg_any() { p.cargo("check -Zcargo-lints -Zcheck-target-cfgs") .masquerade_as_nightly_cargo(&["requires -Zcheck-target-cfgs"]) - // FIXME: We shouldn't be linting `cfg(foo)` because of the `cfg(any())` .with_stderr_data(str![[r#" -[ERROR] [ROOT]/foo/Cargo.toml: unexpected `cfg` condition name: `foo` in `[target.'cfg(foo)'.dependencies]` +[LOCKING] 1 package to latest compatible version +[CHECKING] a v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]) - // nor should we error out because of the level="deny" - .with_status(101) .run(); }