diff --git a/src/cargo/core/compiler/build_context/target_info.rs b/src/cargo/core/compiler/build_context/target_info.rs index 33e0461ca360..4f182421b1e3 100644 --- a/src/cargo/core/compiler/build_context/target_info.rs +++ b/src/cargo/core/compiler/build_context/target_info.rs @@ -364,6 +364,47 @@ 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; + + for line in lines { + check_cfg + .parse_print_check_cfg_line(line) + .with_context(|| format!("unable to parse a line from `--print=check-cfg`"))?; + } + Ok(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 8ddde728a9c3..84a2094744bd 100644 --- a/src/cargo/util/lints.rs +++ b/src/cargo/util/lints.rs @@ -651,13 +651,20 @@ pub fn unexpected_target_cfgs( return Ok(()); }; - if !global_check_cfg.exhaustive { + // 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(()); } - // FIXME: If the `[lints.rust.unexpected_cfgs.check-cfg]` config is set we should - // re-fetch the check-cfg informations with those extra args - for dep in pkg.summary().dependencies() { let Some(platform) = dep.platform() else { continue; @@ -672,7 +679,7 @@ pub fn unexpected_target_cfgs( Cfg::KeyPair(name, value) => (name, Some(value.to_string())), }; - match global_check_cfg.expecteds.get(name) { + match check_cfg.expecteds.get(name) { Some(ExpectedValues::Some(values)) if !values.contains(&value) => { let level = lint_level.to_diagnostic_level(); if lint_level == LintLevel::Forbid || lint_level == LintLevel::Deny { 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 176c2c74de66..e4e22218375a 100644 --- a/tests/testsuite/cfg.rs +++ b/tests/testsuite/cfg.rs @@ -645,7 +645,6 @@ 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] unexpected `cfg` condition name: bar --> Cargo.toml:14:25 @@ -653,18 +652,6 @@ fn unexpected_cfgs_target_with_lint() { 14 | [target."cfg(bar)".dependencies] | ---------- | -[WARNING] unexpected `cfg` condition name: foo for `foo = "foo"` - --> Cargo.toml:11:25 - | -11 | [target.'cfg(foo = "foo")'.dependencies] # should not warn here - | ------------------ - | -[WARNING] unexpected `cfg` condition name: foo - --> Cargo.toml:8:25 - | -8 | [target."cfg(foo)".dependencies] # should not warn here - | ---------- - | [LOCKING] 1 package to latest compatible version [CHECKING] a v0.0.1 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s @@ -819,18 +806,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] unexpected `cfg` condition name: foo - --> Cargo.toml:8:25 - | -8 | [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(); }