@@ -103,6 +103,41 @@ macro_rules! maybe_whole {
103103 } ;
104104}
105105
106+ /// Reparses an invisible-delimited sequence produced by expansion of a
107+ /// declarative macro metavariable. Will panic if called with a `self.token`
108+ /// that is not an `InvisibleOrigin::Metavar` invisible open delimiter.
109+ #[ macro_export]
110+ macro_rules! reparse_metavar_seq {
111+ ( $p: expr, $nt_kind: expr, $nt_res: pat, $ret: expr) => { {
112+ let delim = token:: Delimiter :: Invisible ( token:: InvisibleOrigin :: MetaVar ( $nt_kind) ) ;
113+ $p. expect( & token:: OpenDelim ( delim) ) . expect( "no open delim when reparsing" ) ;
114+ // njn: parse_nonterminal collects token. Should this reparsing call
115+ // not do that?
116+ let Ok ( $nt_res) = $p. parse_nonterminal( $nt_kind) else {
117+ panic!( "failed to reparse" ) ;
118+ } ;
119+ $p. expect( & token:: CloseDelim ( delim) ) . expect( "no close delim when reparsing" ) ;
120+ $ret
121+ } } ;
122+ }
123+
124+ /// Reparses an an invisible-delimited sequence produced by expansion of a
125+ /// declarative macro metavariable, if present.
126+ ///
127+ /// `$nt_kind_pat` and `$nt_kind` are always syntactically identical in
128+ /// practice, but must be specified separately because one is a pattern and one
129+ /// is an expression. Which is annoying but hard to avoid.
130+ #[ macro_export]
131+ macro_rules! maybe_reparse_metavar_seq {
132+ ( $p: expr, $nt_kind_pat: pat, $nt_kind: expr, $nt_res: pat, $ret: expr) => {
133+ if let Some ( $nt_kind_pat) = $p. token. is_metavar_seq( ) {
134+ Some ( crate :: reparse_metavar_seq!( $p, $nt_kind, $nt_res, $ret) )
135+ } else {
136+ None
137+ }
138+ } ;
139+ }
140+
106141/// If the next tokens are ill-formed `$ty::` recover them as `<$ty>::`.
107142#[ macro_export]
108143macro_rules! maybe_recover_from_interpolated_ty_qpath {
@@ -1423,7 +1458,15 @@ impl<'a> Parser<'a> {
14231458 /// so emit a proper diagnostic.
14241459 // Public for rustfmt usage.
14251460 pub fn parse_visibility ( & mut self , fbt : FollowedByType ) -> PResult < ' a , Visibility > {
1426- maybe_whole ! ( self , NtVis , |vis| vis. into_inner( ) ) ;
1461+ if let Some ( vis) = maybe_reparse_metavar_seq ! (
1462+ self ,
1463+ NonterminalKind :: Vis ,
1464+ NonterminalKind :: Vis ,
1465+ ParseNtResult :: Vis ( vis) ,
1466+ vis
1467+ ) {
1468+ return Ok ( vis. into_inner ( ) ) ;
1469+ }
14271470
14281471 if !self . eat_keyword ( kw:: Pub ) {
14291472 // We need a span for our `Spanned<VisibilityKind>`, but there's inherently no
@@ -1604,6 +1647,9 @@ pub enum FlatToken {
16041647#[ derive( Clone , Debug ) ]
16051648pub enum ParseNtResult < NtType > {
16061649 Tt ( TokenTree ) ,
1650+ Vis ( P < ast:: Visibility > ) ,
1651+
1652+ /// This variant will eventually be removed, along with `Token::Interpolate`.
16071653 Nt ( NtType ) ,
16081654}
16091655
@@ -1614,6 +1660,7 @@ impl<T> ParseNtResult<T> {
16141660 {
16151661 match self {
16161662 ParseNtResult :: Tt ( tt) => ParseNtResult :: Tt ( tt) ,
1663+ ParseNtResult :: Vis ( x) => ParseNtResult :: Vis ( x) ,
16171664 ParseNtResult :: Nt ( nt) => ParseNtResult :: Nt ( f ( nt) ) ,
16181665 }
16191666 }
0 commit comments