@@ -109,6 +109,7 @@ impl ArgParser {
109109 parts : & [ Symbol ] ,
110110 psess : & ' sess ParseSess ,
111111 should_emit : ShouldEmit ,
112+ allow_expr_metavar : AllowExprMetavar ,
112113 ) -> Option < Self > {
113114 Some ( match value {
114115 AttrArgs :: Empty => Self :: NoArgs ,
@@ -122,6 +123,7 @@ impl ArgParser {
122123 args. dspan . entire ( ) ,
123124 psess,
124125 ShouldEmit :: ErrorsAndLints { recovery : Recovery :: Forbidden } ,
126+ allow_expr_metavar,
125127 ) {
126128 Ok ( p) => return Some ( ArgParser :: List ( p) ) ,
127129 Err ( e) => {
@@ -147,9 +149,15 @@ impl ArgParser {
147149 }
148150
149151 Self :: List (
150- MetaItemListParser :: new ( & args. tokens , args. dspan . entire ( ) , psess, should_emit)
151- . map_err ( |e| should_emit. emit_err ( e) )
152- . ok ( ) ?,
152+ MetaItemListParser :: new (
153+ & args. tokens ,
154+ args. dspan . entire ( ) ,
155+ psess,
156+ should_emit,
157+ allow_expr_metavar,
158+ )
159+ . map_err ( |e| should_emit. emit_err ( e) )
160+ . ok ( ) ?,
153161 )
154162 }
155163 AttrArgs :: Eq { eq_span, expr } => Self :: NameValue ( NameValueParser {
@@ -217,8 +225,9 @@ impl MetaItemOrLitParser {
217225 pub fn parse_single < ' sess > (
218226 parser : & mut Parser < ' sess > ,
219227 should_emit : ShouldEmit ,
228+ allow_expr_metavar : AllowExprMetavar ,
220229 ) -> PResult < ' sess , MetaItemOrLitParser > {
221- let mut this = MetaItemListParserContext { parser, should_emit } ;
230+ let mut this = MetaItemListParserContext { parser, should_emit, allow_expr_metavar } ;
222231 this. parse_meta_item_inner ( )
223232 }
224233
@@ -404,9 +413,19 @@ fn expr_to_lit<'sess>(
404413 }
405414}
406415
416+ /// Whether expansions of `expr` metavariables from decrarative macros
417+ /// are permitted. Used when parsing meta items; currently, only `cfg` predicates
418+ /// enable this option
419+ #[ derive( Clone , Copy , PartialEq , Eq ) ]
420+ pub enum AllowExprMetavar {
421+ No ,
422+ Yes ,
423+ }
424+
407425struct MetaItemListParserContext < ' a , ' sess > {
408426 parser : & ' a mut Parser < ' sess > ,
409427 should_emit : ShouldEmit ,
428+ allow_expr_metavar : AllowExprMetavar ,
410429}
411430
412431impl < ' a , ' sess > MetaItemListParserContext < ' a , ' sess > {
@@ -447,20 +466,44 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
447466 Ok ( lit)
448467 }
449468
450- fn parse_attr_item ( & mut self ) -> PResult < ' sess , MetaItemParser > {
451- if let Some ( MetaVarKind :: Meta { has_meta_form } ) = self . parser . token . is_metavar_seq ( ) {
452- return if has_meta_form {
453- let attr_item = self
454- . parser
455- . eat_metavar_seq ( MetaVarKind :: Meta { has_meta_form : true } , |this| {
456- MetaItemListParserContext { parser : this, should_emit : self . should_emit }
457- . parse_attr_item ( )
458- } )
459- . unwrap ( ) ;
460- Ok ( attr_item)
461- } else {
462- self . parser . unexpected_any ( )
463- } ;
469+ fn parse_meta_item ( & mut self ) -> PResult < ' sess , MetaItemParser > {
470+ if let Some ( metavar) = self . parser . token . is_metavar_seq ( ) {
471+ match ( metavar, self . allow_expr_metavar ) {
472+ ( kind @ MetaVarKind :: Expr { .. } , AllowExprMetavar :: Yes ) => {
473+ return self
474+ . parser
475+ . eat_metavar_seq ( kind, |this| {
476+ MetaItemListParserContext {
477+ parser : this,
478+ should_emit : self . should_emit ,
479+ allow_expr_metavar : AllowExprMetavar :: Yes ,
480+ }
481+ . parse_meta_item ( )
482+ } )
483+ . ok_or_else ( || {
484+ self . parser . unexpected_any :: < core:: convert:: Infallible > ( ) . unwrap_err ( )
485+ } ) ;
486+ }
487+ ( MetaVarKind :: Meta { has_meta_form } , _) => {
488+ return if has_meta_form {
489+ let attr_item = self
490+ . parser
491+ . eat_metavar_seq ( MetaVarKind :: Meta { has_meta_form : true } , |this| {
492+ MetaItemListParserContext {
493+ parser : this,
494+ should_emit : self . should_emit ,
495+ allow_expr_metavar : self . allow_expr_metavar ,
496+ }
497+ . parse_meta_item ( )
498+ } )
499+ . unwrap ( ) ;
500+ Ok ( attr_item)
501+ } else {
502+ self . parser . unexpected_any ( )
503+ } ;
504+ }
505+ _ => { }
506+ }
464507 }
465508
466509 let path = self . parser . parse_path ( PathStyle :: Mod ) ?;
@@ -469,8 +512,12 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
469512 let args = if self . parser . check ( exp ! ( OpenParen ) ) {
470513 let start = self . parser . token . span ;
471514 let ( sub_parsers, _) = self . parser . parse_paren_comma_seq ( |parser| {
472- MetaItemListParserContext { parser, should_emit : self . should_emit }
473- . parse_meta_item_inner ( )
515+ MetaItemListParserContext {
516+ parser,
517+ should_emit : self . should_emit ,
518+ allow_expr_metavar : self . allow_expr_metavar ,
519+ }
520+ . parse_meta_item_inner ( )
474521 } ) ?;
475522 let end = self . parser . prev_token . span ;
476523 ArgParser :: List ( MetaItemListParser { sub_parsers, span : start. with_hi ( end. hi ( ) ) } )
@@ -492,7 +539,7 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
492539 Ok ( MetaItemOrLitParser :: Lit ( self . unsuffixed_meta_item_from_lit ( token_lit) ?) )
493540 } else {
494541 let prev_pros = self . parser . approx_token_stream_pos ( ) ;
495- match self . parse_attr_item ( ) {
542+ match self . parse_meta_item ( ) {
496543 Ok ( item) => Ok ( MetaItemOrLitParser :: MetaItemParser ( item) ) ,
497544 Err ( err) => {
498545 // If `parse_attr_item` made any progress, it likely has a more precise error we should prefer
@@ -580,13 +627,15 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
580627 psess : & ' sess ParseSess ,
581628 span : Span ,
582629 should_emit : ShouldEmit ,
630+ allow_expr_metavar : AllowExprMetavar ,
583631 ) -> PResult < ' sess , MetaItemListParser > {
584632 let mut parser = Parser :: new ( psess, tokens, None ) ;
585633 if let ShouldEmit :: ErrorsAndLints { recovery } = should_emit {
586634 parser = parser. recovery ( recovery) ;
587635 }
588636
589- let mut this = MetaItemListParserContext { parser : & mut parser, should_emit } ;
637+ let mut this =
638+ MetaItemListParserContext { parser : & mut parser, should_emit, allow_expr_metavar } ;
590639
591640 // Presumably, the majority of the time there will only be one attr.
592641 let mut sub_parsers = ThinVec :: with_capacity ( 1 ) ;
@@ -618,8 +667,15 @@ impl MetaItemListParser {
618667 span : Span ,
619668 psess : & ' sess ParseSess ,
620669 should_emit : ShouldEmit ,
670+ allow_expr_metavar : AllowExprMetavar ,
621671 ) -> Result < Self , Diag < ' sess > > {
622- MetaItemListParserContext :: parse ( tokens. clone ( ) , psess, span, should_emit)
672+ MetaItemListParserContext :: parse (
673+ tokens. clone ( ) ,
674+ psess,
675+ span,
676+ should_emit,
677+ allow_expr_metavar,
678+ )
623679 }
624680
625681 /// Lets you pick and choose as what you want to parse each element in the list
0 commit comments