@@ -18,7 +18,7 @@ pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
1818pub use path:: PathStyle ;
1919
2020use rustc_ast:: ptr:: P ;
21- use rustc_ast:: token:: { self , Delimiter , Nonterminal , Token , TokenKind } ;
21+ use rustc_ast:: token:: { self , Delimiter , Nonterminal , NonterminalKind , Token , TokenKind } ;
2222use rustc_ast:: tokenstream:: { AttributesData , DelimSpan , Spacing } ;
2323use rustc_ast:: tokenstream:: { TokenStream , TokenTree , TokenTreeCursor } ;
2424use rustc_ast:: util:: case:: Case ;
@@ -100,6 +100,41 @@ macro_rules! maybe_whole {
100100 } ;
101101}
102102
103+ /// Reparses an invisible-delimited sequence produced by expansion of a
104+ /// declarative macro metavariable. Will panic if called with a `self.token`
105+ /// that is not an `InvisibleSource::Metavar` invisible open delimiter.
106+ #[ macro_export]
107+ macro_rules! reparse_metavar_seq {
108+ ( $p: expr, $nt_kind: expr, $nt_res: pat, $ret: expr) => { {
109+ let delim = token:: Delimiter :: Invisible ( token:: InvisibleSource :: MetaVar ( $nt_kind) ) ;
110+ $p. expect( & token:: OpenDelim ( delim) ) . expect( "no open delim when reparsing" ) ;
111+ // njn: parse_nonterminal collects token. Should this reparsing call
112+ // not do that?
113+ let Ok ( $nt_res) = $p. parse_nonterminal( $nt_kind) else {
114+ panic!( "failed to reparse" ) ;
115+ } ;
116+ $p. expect( & token:: CloseDelim ( delim) ) . expect( "no close delim when reparsing" ) ;
117+ $ret
118+ } } ;
119+ }
120+
121+ /// Reparses an an invisible-delimited sequence produced by expansion of a
122+ /// declarative macro metavariable, if present.
123+ ///
124+ /// `$nt_kind_pat` and `$nt_kind` are always syntactically identical in
125+ /// practice, but must be specified separately because one is a pattern and one
126+ /// is an expression. Which is annoying but hard to avoid.
127+ #[ macro_export]
128+ macro_rules! maybe_reparse_metavar_seq {
129+ ( $p: expr, $nt_kind_pat: pat, $nt_kind: expr, $nt_res: pat, $ret: expr) => {
130+ if let Some ( $nt_kind_pat) = $p. token. is_metavar_seq( ) {
131+ Some ( crate :: reparse_metavar_seq!( $p, $nt_kind, $nt_res, $ret) )
132+ } else {
133+ None
134+ }
135+ } ;
136+ }
137+
103138/// If the next tokens are ill-formed `$ty::` recover them as `<$ty>::`.
104139#[ macro_export]
105140macro_rules! maybe_recover_from_interpolated_ty_qpath {
@@ -1330,7 +1365,15 @@ impl<'a> Parser<'a> {
13301365 /// so emit a proper diagnostic.
13311366 // Public for rustfmt usage.
13321367 pub fn parse_visibility ( & mut self , fbt : FollowedByType ) -> PResult < ' a , Visibility > {
1333- maybe_whole ! ( self , NtVis , |x| x. into_inner( ) ) ;
1368+ if let Some ( vis) = maybe_reparse_metavar_seq ! (
1369+ self ,
1370+ NonterminalKind :: Vis ,
1371+ NonterminalKind :: Vis ,
1372+ ParseNtResult :: Vis ( vis) ,
1373+ vis
1374+ ) {
1375+ return Ok ( vis. into_inner ( ) ) ;
1376+ }
13341377
13351378 if !self . eat_keyword ( kw:: Pub ) {
13361379 // We need a span for our `Spanned<VisibilityKind>`, but there's inherently no
@@ -1515,6 +1558,8 @@ pub enum FlatToken {
15151558#[ derive( Clone , Debug ) ]
15161559pub enum ParseNtResult {
15171560 Tt ( TokenTree ) ,
1561+ Vis ( P < ast:: Visibility > ) ,
15181562
1563+ /// This case will eventually be removed, along with `Token::Interpolate`.
15191564 Nt ( Lrc < Nonterminal > ) ,
15201565}
0 commit comments