@@ -866,18 +866,39 @@ fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Result<Nonterminal, (
866866}
867867
868868fn parse_nt_inner < ' a > ( p : & mut Parser < ' a > , sp : Span , name : Symbol ) -> PResult < ' a , Nonterminal > {
869+ // Any `Nonterminal` which stores its tokens (currently `NtItem` and `NtExpr`)
870+ // needs to have them force-captured here.
871+ // A `macro_rules!` invocation may pass a captured item/expr to a proc-macro,
872+ // which requires having captured tokens available. Since we cannot determine
873+ // in advance whether or not a proc-macro will be (transitively) invoked,
874+ // we always capture tokens for any `Nonterminal` which needs them.
869875 Ok ( match name {
870- sym:: item => match p. parse_item ( ) ? {
871- Some ( i) => token:: NtItem ( i) ,
872- None => return Err ( p. struct_span_err ( p. token . span , "expected an item keyword" ) ) ,
876+ sym:: item => match p. collect_tokens ( |this| this. parse_item ( ) ) ? {
877+ ( Some ( mut item) , tokens) => {
878+ // If we captured tokens during parsing (due to outer attributes),
879+ // use those.
880+ if item. tokens . is_none ( ) {
881+ item. tokens = Some ( tokens) ;
882+ }
883+ token:: NtItem ( item)
884+ }
885+ ( None , _) => return Err ( p. struct_span_err ( p. token . span , "expected an item keyword" ) ) ,
873886 } ,
874887 sym:: block => token:: NtBlock ( p. parse_block ( ) ?) ,
875888 sym:: stmt => match p. parse_stmt ( ) ? {
876889 Some ( s) => token:: NtStmt ( s) ,
877890 None => return Err ( p. struct_span_err ( p. token . span , "expected a statement" ) ) ,
878891 } ,
879892 sym:: pat => token:: NtPat ( p. parse_pat ( None ) ?) ,
880- sym:: expr => token:: NtExpr ( p. parse_expr ( ) ?) ,
893+ sym:: expr => {
894+ let ( mut expr, tokens) = p. collect_tokens ( |this| this. parse_expr ( ) ) ?;
895+ // If we captured tokens during parsing (due to outer attributes),
896+ // use those.
897+ if expr. tokens . is_none ( ) {
898+ expr. tokens = Some ( tokens) ;
899+ }
900+ token:: NtExpr ( expr)
901+ }
881902 sym:: literal => token:: NtLiteral ( p. parse_literal_maybe_minus ( ) ?) ,
882903 sym:: ty => token:: NtTy ( p. parse_ty ( ) ?) ,
883904 // this could be handled like a token, since it is one
0 commit comments