Skip to content

Commit bd376fb

Browse files
committed
Make unexpected target cfgs respect Rust unexpected_cfgs lint
1 parent 4109e11 commit bd376fb

File tree

4 files changed

+122
-6
lines changed

4 files changed

+122
-6
lines changed

crates/cargo-platform/src/cfg.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ impl CfgExpr {
9090
}
9191
}
9292

93-
pub fn fold<E>(&self, f: &impl Fn(&Cfg) -> Result<(), E>) -> Result<(), E> {
93+
pub fn fold<E>(&self, f: &mut impl FnMut(&Cfg) -> Result<(), E>) -> Result<(), E> {
9494
match *self {
9595
CfgExpr::Not(ref e) => CfgExpr::fold(e, f),
9696
CfgExpr::All(ref e) | CfgExpr::Any(ref e) => {

src/cargo/ops/cargo_compile/mod.rs

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ use crate::ops;
5757
use crate::ops::resolve::WorkspaceResolve;
5858
use crate::util::context::GlobalContext;
5959
use crate::util::interning::InternedString;
60+
use crate::util::lints::LintLevel;
6061
use crate::util::{CargoResult, Rustc, StableHasher};
6162

6263
mod compile_filter;
@@ -482,6 +483,9 @@ pub fn create_bcx<'a, 'gctx>(
482483

483484
if let Some(check_cfg) = target_data.check_cfg() {
484485
if check_cfg.exhaustive {
486+
let mut error_count = 0;
487+
let mut max_lint_level = LintLevel::Allow;
488+
485489
let target_cfgs = gctx.target_cfgs()?;
486490
for (key, _fields) in target_cfgs {
487491
if !key.starts_with("cfg(") || !key.ends_with(')') {
@@ -493,14 +497,36 @@ pub fn create_bcx<'a, 'gctx>(
493497
continue;
494498
};
495499

496-
warn_on_unexpected_cfgs(gctx, check_cfg, &cfg_expr, None, "")?;
500+
warn_on_unexpected_cfgs(
501+
gctx,
502+
check_cfg,
503+
&cfg_expr,
504+
LintLevel::Warn,
505+
&mut error_count,
506+
None,
507+
"",
508+
)?;
497509
}
498510

499511
for unit in &units {
500512
if !unit.show_warnings(gctx) {
501513
continue;
502514
}
503515

516+
let mut lint_level = LintLevel::Warn;
517+
if let Ok(Some(lints)) = unit.pkg.manifest().normalized_toml().normalized_lints() {
518+
if let Some(rust_lints) = lints.get("rust") {
519+
if let Some(unexpected_cfgs) = rust_lints.get("unexpected_cfgs") {
520+
lint_level = unexpected_cfgs.level().into();
521+
max_lint_level = std::cmp::max(max_lint_level, lint_level);
522+
}
523+
}
524+
}
525+
526+
if lint_level == LintLevel::Allow {
527+
continue;
528+
}
529+
504530
let specific_check_cfg =
505531
get_specific_check_cfg_for_unit(gctx, &target_data.rustc, unit)?;
506532
let check_cfg = specific_check_cfg.as_ref().unwrap_or(check_cfg);
@@ -521,11 +547,19 @@ pub fn create_bcx<'a, 'gctx>(
521547
gctx,
522548
check_cfg,
523549
cfg_expr,
550+
lint_level,
551+
&mut error_count,
524552
Some(unit.pkg.manifest_path()),
525553
".dependencies",
526554
)?;
527555
}
528556
}
557+
558+
if max_lint_level >= LintLevel::Deny && error_count > 0 {
559+
Err(anyhow::anyhow!(
560+
"encountered {error_count} `unexpected_cfgs` error(s)",
561+
))?
562+
}
529563
}
530564
}
531565

@@ -613,6 +647,8 @@ fn warn_on_unexpected_cfgs(
613647
gctx: &GlobalContext,
614648
check_cfg: &CheckCfg,
615649
cfg_expr: &CfgExpr,
650+
lint_level: LintLevel,
651+
error_count: &mut u32,
616652
path: Option<&Path>,
617653
suffix: &str,
618654
) -> CargoResult<()> {
@@ -622,7 +658,16 @@ fn warn_on_unexpected_cfgs(
622658
"".to_string()
623659
};
624660

625-
cfg_expr.fold(&|cfg| -> CargoResult<()> {
661+
let mut emit_lint = |msg| {
662+
*error_count += 1;
663+
match lint_level {
664+
LintLevel::Warn => gctx.shell().warn(msg),
665+
LintLevel::Deny | LintLevel::Forbid => gctx.shell().error(msg),
666+
LintLevel::Allow => Ok(()),
667+
}
668+
};
669+
670+
cfg_expr.fold(&mut |cfg| -> CargoResult<()> {
626671
let (name, value) = match cfg {
627672
Cfg::Name(name) => (name, None),
628673
Cfg::KeyPair(name, value) => (name, Some(value.to_string())),
@@ -635,12 +680,12 @@ fn warn_on_unexpected_cfgs(
635680
} else {
636681
"(none)"
637682
};
638-
gctx.shell().warn(format!(
683+
emit_lint(format!(
639684
"{prefix}unexpected `cfg` condition value: `{value}` for `{cfg}` in `[target.'cfg({cfg_expr})'{suffix}]`"
640685
))?;
641686
}
642687
None => {
643-
gctx.shell().warn(format!(
688+
emit_lint(format!(
644689
"{prefix}unexpected `cfg` condition name: `{name}`{cfg} in `[target.'cfg({cfg_expr})'{suffix}]`",
645690
cfg = if value.is_some() {
646691
format!(" for `{cfg}`")

src/cargo/util/lints.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ impl Lint {
329329
}
330330
}
331331

332-
#[derive(Copy, Clone, Debug, PartialEq)]
332+
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
333333
pub enum LintLevel {
334334
Allow,
335335
Warn,

tests/testsuite/cfg.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,77 @@ fn unexpected_cfgs_target_with_lint() {
635635
.run();
636636
}
637637

638+
#[cargo_test(nightly, reason = "--print=check-cfg is unstable in rustc")]
639+
fn unexpected_cfgs_target_lint_level_allow() {
640+
let p = project()
641+
.file(
642+
"Cargo.toml",
643+
r#"
644+
[package]
645+
name = "a"
646+
version = "0.0.1"
647+
edition = "2015"
648+
authors = []
649+
650+
[target."cfg(foo)".dependencies]
651+
b = { path = 'b' }
652+
653+
[lints.rust.unexpected_cfgs]
654+
level = "allow"
655+
"#,
656+
)
657+
.file("src/lib.rs", "")
658+
.file("b/Cargo.toml", &basic_manifest("b", "0.0.1"))
659+
.file("b/src/lib.rs", "")
660+
.build();
661+
662+
p.cargo("check -Zcheck-target-cfgs")
663+
.masquerade_as_nightly_cargo(&["requires -Zcheck-target-cfgs"])
664+
.with_stderr_data(str![[r#"
665+
[LOCKING] 1 package to latest compatible version
666+
[CHECKING] a v0.0.1 ([ROOT]/foo)
667+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
668+
669+
"#]])
670+
.run();
671+
}
672+
673+
#[cargo_test(nightly, reason = "--print=check-cfg is unstable in rustc")]
674+
fn unexpected_cfgs_target_lint_level_deny() {
675+
let p = project()
676+
.file(
677+
"Cargo.toml",
678+
r#"
679+
[package]
680+
name = "a"
681+
version = "0.0.1"
682+
edition = "2015"
683+
authors = []
684+
685+
[target."cfg(foo)".dependencies]
686+
b = { path = 'b' }
687+
688+
[lints.rust.unexpected_cfgs]
689+
level = "deny"
690+
"#,
691+
)
692+
.file("src/lib.rs", "")
693+
.file("b/Cargo.toml", &basic_manifest("b", "0.0.1"))
694+
.file("b/src/lib.rs", "")
695+
.build();
696+
697+
p.cargo("check -Zcheck-target-cfgs")
698+
.masquerade_as_nightly_cargo(&["requires -Zcheck-target-cfgs"])
699+
.with_stderr_data(str![[r#"
700+
[LOCKING] 1 package to latest compatible version
701+
[ERROR] [ROOT]/foo/Cargo.toml: unexpected `cfg` condition name: `foo` in `[target.'cfg(foo)'.dependencies]`
702+
[ERROR] encountered 1 `unexpected_cfgs` error(s)
703+
704+
"#]])
705+
.with_status(101)
706+
.run();
707+
}
708+
638709
#[cargo_test(nightly, reason = "--print=check-cfg is unstable in rustc")]
639710
fn unexpected_cfgs_target_cfg_any() {
640711
let p = project()

0 commit comments

Comments
 (0)