@@ -866,18 +866,39 @@ fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Result<Nonterminal, (
866
866
}
867
867
868
868
fn 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.
869
875
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" ) ) ,
873
886
} ,
874
887
sym:: block => token:: NtBlock ( p. parse_block ( ) ?) ,
875
888
sym:: stmt => match p. parse_stmt ( ) ? {
876
889
Some ( s) => token:: NtStmt ( s) ,
877
890
None => return Err ( p. struct_span_err ( p. token . span , "expected a statement" ) ) ,
878
891
} ,
879
892
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
+ }
881
902
sym:: literal => token:: NtLiteral ( p. parse_literal_maybe_minus ( ) ?) ,
882
903
sym:: ty => token:: NtTy ( p. parse_ty ( ) ?) ,
883
904
// this could be handled like a token, since it is one
0 commit comments