@@ -57,6 +57,7 @@ use crate::ops;
5757use crate :: ops:: resolve:: WorkspaceResolve ;
5858use crate :: util:: context:: GlobalContext ;
5959use crate :: util:: interning:: InternedString ;
60+ use crate :: util:: lints:: LintLevel ;
6061use crate :: util:: { CargoResult , Rustc , StableHasher } ;
6162
6263mod 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}`" )
0 commit comments