@@ -454,6 +454,15 @@ pub fn find_crate_name(sess: &Session, attrs: &[Attribute]) -> Option<Symbol> {
454454 sess. first_attr_value_str_by_name ( attrs, sym:: crate_name)
455455}
456456
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+
457466/// Tests if a cfg-pattern matches the cfg set
458467pub fn cfg_matches (
459468 cfg : & ast:: MetaItem ,
@@ -462,70 +471,42 @@ pub fn cfg_matches(
462471 features : Option < & Features > ,
463472) -> bool {
464473 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 ) ,
485483 ) ;
486- true
487484 }
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+ ) ;
518499 }
519- sess. config . contains ( & ( name, value) )
520500 }
521501 }
502+ sess. config . contains ( & ( cfg. name , cfg. value ) )
522503 } )
523504}
524505
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 ) ;
527508 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) ;
529510 }
530511}
531512
@@ -563,11 +544,11 @@ pub fn eval_condition(
563544 cfg : & ast:: MetaItem ,
564545 sess : & ParseSess ,
565546 features : Option < & Features > ,
566- eval : & mut impl FnMut ( & ast :: MetaItem ) -> bool ,
547+ eval : & mut impl FnMut ( Condition ) -> bool ,
567548) -> bool {
568549 match cfg. kind {
569550 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) ;
571552 let ( min_version, span) = match & mis[ ..] {
572553 [ NestedMetaItem :: Literal ( Lit { kind : LitKind :: Str ( sym, ..) , span, .. } ) ] => {
573554 ( sym, span)
@@ -649,6 +630,25 @@ pub fn eval_condition(
649630
650631 !eval_condition ( mis[ 0 ] . meta_item ( ) . unwrap ( ) , sess, features, eval)
651632 }
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+ }
652652 _ => {
653653 struct_span_err ! (
654654 sess. span_diagnostic,
@@ -662,7 +662,32 @@ pub fn eval_condition(
662662 }
663663 }
664664 }
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+ }
666691 }
667692}
668693
0 commit comments