@@ -454,6 +454,15 @@ pub fn find_crate_name(sess: &Session, attrs: &[Attribute]) -> Option<Symbol> {
454
454
sess. first_attr_value_str_by_name ( attrs, sym:: crate_name)
455
455
}
456
456
457
+ #[ derive( Clone , Debug ) ]
458
+ pub struct Condition {
459
+ pub name : Symbol ,
460
+ pub name_span : Span ,
461
+ pub value : Option < Symbol > ,
462
+ pub value_span : Option < Span > ,
463
+ pub span : Span ,
464
+ }
465
+
457
466
/// Tests if a cfg-pattern matches the cfg set
458
467
pub fn cfg_matches (
459
468
cfg : & ast:: MetaItem ,
@@ -462,70 +471,42 @@ pub fn cfg_matches(
462
471
features : Option < & Features > ,
463
472
) -> bool {
464
473
eval_condition ( cfg, sess, features, & mut |cfg| {
465
- try_gate_cfg ( cfg, sess, features) ;
466
- let error = |span, msg| {
467
- sess. span_diagnostic . span_err ( span, msg) ;
468
- true
469
- } ;
470
- if cfg. path . segments . len ( ) != 1 {
471
- return error ( cfg. path . span , "`cfg` predicate key must be an identifier" ) ;
472
- }
473
- match & cfg. kind {
474
- MetaItemKind :: List ( ..) => {
475
- error ( cfg. span , "unexpected parentheses after `cfg` predicate key" )
476
- }
477
- MetaItemKind :: NameValue ( lit) if !lit. kind . is_str ( ) => {
478
- handle_errors (
479
- sess,
480
- lit. span ,
481
- AttrError :: UnsupportedLiteral (
482
- "literal in `cfg` predicate value must be a string" ,
483
- lit. kind . is_bytestr ( ) ,
484
- ) ,
474
+ try_gate_cfg ( cfg. name , cfg. span , sess, features) ;
475
+ if let Some ( names_valid) = & sess. check_config . names_valid {
476
+ if !names_valid. contains ( & cfg. name ) {
477
+ sess. buffer_lint_with_diagnostic (
478
+ UNEXPECTED_CFGS ,
479
+ cfg. span ,
480
+ lint_node_id,
481
+ "unexpected `cfg` condition name" ,
482
+ BuiltinLintDiagnostics :: UnexpectedCfg ( ( cfg. name , cfg. name_span ) , None ) ,
485
483
) ;
486
- true
487
484
}
488
- MetaItemKind :: NameValue ( ..) | MetaItemKind :: Word => {
489
- let ident = cfg. ident ( ) . expect ( "multi-segment cfg predicate" ) ;
490
- let name = ident. name ;
491
- let value = cfg. value_str ( ) ;
492
- if let Some ( names_valid) = & sess. check_config . names_valid {
493
- if !names_valid. contains ( & name) {
494
- sess. buffer_lint_with_diagnostic (
495
- UNEXPECTED_CFGS ,
496
- cfg. span ,
497
- lint_node_id,
498
- "unexpected `cfg` condition name" ,
499
- BuiltinLintDiagnostics :: UnexpectedCfg ( ( name, ident. span ) , None ) ,
500
- ) ;
501
- }
502
- }
503
- if let Some ( value) = value {
504
- if let Some ( values) = & sess. check_config . values_valid . get ( & name) {
505
- if !values. contains ( & value) {
506
- sess. buffer_lint_with_diagnostic (
507
- UNEXPECTED_CFGS ,
508
- cfg. span ,
509
- lint_node_id,
510
- "unexpected `cfg` condition value" ,
511
- BuiltinLintDiagnostics :: UnexpectedCfg (
512
- ( name, ident. span ) ,
513
- Some ( ( value, cfg. name_value_literal_span ( ) . unwrap ( ) ) ) ,
514
- ) ,
515
- ) ;
516
- }
517
- }
485
+ }
486
+ if let Some ( value) = cfg. value {
487
+ if let Some ( values) = & sess. check_config . values_valid . get ( & cfg. name ) {
488
+ if !values. contains ( & value) {
489
+ sess. buffer_lint_with_diagnostic (
490
+ UNEXPECTED_CFGS ,
491
+ cfg. span ,
492
+ lint_node_id,
493
+ "unexpected `cfg` condition value" ,
494
+ BuiltinLintDiagnostics :: UnexpectedCfg (
495
+ ( cfg. name , cfg. name_span ) ,
496
+ cfg. value_span . map ( |vs| ( value, vs) ) ,
497
+ ) ,
498
+ ) ;
518
499
}
519
- sess. config . contains ( & ( name, value) )
520
500
}
521
501
}
502
+ sess. config . contains ( & ( cfg. name , cfg. value ) )
522
503
} )
523
504
}
524
505
525
- fn try_gate_cfg ( cfg : & ast :: MetaItem , sess : & ParseSess , features : Option < & Features > ) {
526
- let gate = find_gated_cfg ( |sym| cfg . has_name ( sym) ) ;
506
+ fn try_gate_cfg ( name : Symbol , span : Span , sess : & ParseSess , features : Option < & Features > ) {
507
+ let gate = find_gated_cfg ( |sym| sym == name ) ;
527
508
if let ( Some ( feats) , Some ( gated_cfg) ) = ( features, gate) {
528
- gate_cfg ( & gated_cfg, cfg . span , sess, feats) ;
509
+ gate_cfg ( & gated_cfg, span, sess, feats) ;
529
510
}
530
511
}
531
512
@@ -563,11 +544,11 @@ pub fn eval_condition(
563
544
cfg : & ast:: MetaItem ,
564
545
sess : & ParseSess ,
565
546
features : Option < & Features > ,
566
- eval : & mut impl FnMut ( & ast :: MetaItem ) -> bool ,
547
+ eval : & mut impl FnMut ( Condition ) -> bool ,
567
548
) -> bool {
568
549
match cfg. kind {
569
550
ast:: MetaItemKind :: List ( ref mis) if cfg. name_or_empty ( ) == sym:: version => {
570
- try_gate_cfg ( cfg, sess, features) ;
551
+ try_gate_cfg ( sym :: version , cfg. span , sess, features) ;
571
552
let ( min_version, span) = match & mis[ ..] {
572
553
[ NestedMetaItem :: Literal ( Lit { kind : LitKind :: Str ( sym, ..) , span, .. } ) ] => {
573
554
( sym, span)
@@ -649,6 +630,25 @@ pub fn eval_condition(
649
630
650
631
!eval_condition ( mis[ 0 ] . meta_item ( ) . unwrap ( ) , sess, features, eval)
651
632
}
633
+ sym:: target => {
634
+ if let Some ( features) = features && !features. cfg_target_compact {
635
+ feature_err (
636
+ sess,
637
+ sym:: cfg_target_compact,
638
+ cfg. span ,
639
+ & "compact `cfg(target(..))` is experimental and subject to change"
640
+ ) . emit ( ) ;
641
+ }
642
+
643
+ mis. iter ( ) . fold ( true , |res, mi| {
644
+ let mut mi = mi. meta_item ( ) . unwrap ( ) . clone ( ) ;
645
+ if let [ seg, ..] = & mut mi. path . segments [ ..] {
646
+ seg. ident . name = Symbol :: intern ( & format ! ( "target_{}" , seg. ident. name) ) ;
647
+ }
648
+
649
+ res & eval_condition ( & mi, sess, features, eval)
650
+ } )
651
+ }
652
652
_ => {
653
653
struct_span_err ! (
654
654
sess. span_diagnostic,
@@ -662,7 +662,32 @@ pub fn eval_condition(
662
662
}
663
663
}
664
664
}
665
- ast:: MetaItemKind :: Word | ast:: MetaItemKind :: NameValue ( ..) => eval ( cfg) ,
665
+ ast:: MetaItemKind :: Word | MetaItemKind :: NameValue ( ..) if cfg. path . segments . len ( ) != 1 => {
666
+ sess. span_diagnostic
667
+ . span_err ( cfg. path . span , "`cfg` predicate key must be an identifier" ) ;
668
+ true
669
+ }
670
+ MetaItemKind :: NameValue ( ref lit) if !lit. kind . is_str ( ) => {
671
+ handle_errors (
672
+ sess,
673
+ lit. span ,
674
+ AttrError :: UnsupportedLiteral (
675
+ "literal in `cfg` predicate value must be a string" ,
676
+ lit. kind . is_bytestr ( ) ,
677
+ ) ,
678
+ ) ;
679
+ true
680
+ }
681
+ ast:: MetaItemKind :: Word | ast:: MetaItemKind :: NameValue ( ..) => {
682
+ let ident = cfg. ident ( ) . expect ( "multi-segment cfg predicate" ) ;
683
+ eval ( Condition {
684
+ name : ident. name ,
685
+ name_span : ident. span ,
686
+ value : cfg. value_str ( ) ,
687
+ value_span : cfg. name_value_literal_span ( ) ,
688
+ span : cfg. span ,
689
+ } )
690
+ }
666
691
}
667
692
}
668
693
0 commit comments