@@ -104,6 +104,41 @@ macro_rules! maybe_whole {
104104 } ;
105105}
106106
107+ /// Reparses an invisible-delimited sequence produced by expansion of a
108+ /// declarative macro metavariable. Will panic if called with a `self.token`
109+ /// that is not an `InvisibleOrigin::Metavar` invisible open delimiter.
110+ #[ macro_export]
111+ macro_rules! reparse_metavar_seq {
112+ ( $p: expr, $nt_kind: expr, $nt_res: pat, $ret: expr) => { {
113+ let delim = token:: Delimiter :: Invisible ( token:: InvisibleOrigin :: MetaVar ( $nt_kind) ) ;
114+ $p. expect( & token:: OpenDelim ( delim) ) . expect( "no open delim when reparsing" ) ;
115+ // njn: parse_nonterminal collects token. Should this reparsing call
116+ // not do that?
117+ let Ok ( $nt_res) = $p. parse_nonterminal( $nt_kind) else {
118+ panic!( "failed to reparse" ) ;
119+ } ;
120+ $p. expect( & token:: CloseDelim ( delim) ) . expect( "no close delim when reparsing" ) ;
121+ $ret
122+ } } ;
123+ }
124+
125+ /// Reparses an an invisible-delimited sequence produced by expansion of a
126+ /// declarative macro metavariable, if present.
127+ ///
128+ /// `$nt_kind_pat` and `$nt_kind` are always syntactically identical in
129+ /// practice, but must be specified separately because one is a pattern and one
130+ /// is an expression. Which is annoying but hard to avoid.
131+ #[ macro_export]
132+ macro_rules! maybe_reparse_metavar_seq {
133+ ( $p: expr, $nt_kind_pat: pat, $nt_kind: expr, $nt_res: pat, $ret: expr) => {
134+ if let Some ( $nt_kind_pat) = $p. token. is_metavar_seq( ) {
135+ Some ( crate :: reparse_metavar_seq!( $p, $nt_kind, $nt_res, $ret) )
136+ } else {
137+ None
138+ }
139+ } ;
140+ }
141+
107142/// If the next tokens are ill-formed `$ty::` recover them as `<$ty>::`.
108143#[ macro_export]
109144macro_rules! maybe_recover_from_interpolated_ty_qpath {
@@ -1440,7 +1475,15 @@ impl<'a> Parser<'a> {
14401475 /// so emit a proper diagnostic.
14411476 // Public for rustfmt usage.
14421477 pub fn parse_visibility ( & mut self , fbt : FollowedByType ) -> PResult < ' a , Visibility > {
1443- maybe_whole ! ( self , NtVis , |vis| vis. into_inner( ) ) ;
1478+ if let Some ( vis) = maybe_reparse_metavar_seq ! (
1479+ self ,
1480+ NonterminalKind :: Vis ,
1481+ NonterminalKind :: Vis ,
1482+ ParseNtResult :: Vis ( vis) ,
1483+ vis
1484+ ) {
1485+ return Ok ( vis. into_inner ( ) ) ;
1486+ }
14441487
14451488 if !self . eat_keyword ( kw:: Pub ) {
14461489 // We need a span for our `Spanned<VisibilityKind>`, but there's inherently no
@@ -1621,6 +1664,9 @@ pub enum FlatToken {
16211664#[ derive( Clone , Debug ) ]
16221665pub enum ParseNtResult < NtType > {
16231666 Tt ( TokenTree ) ,
1667+ Vis ( P < ast:: Visibility > ) ,
1668+
1669+ /// This variant will eventually be removed, along with `Token::Interpolate`.
16241670 Nt ( NtType ) ,
16251671}
16261672
@@ -1631,6 +1677,7 @@ impl<T> ParseNtResult<T> {
16311677 {
16321678 match self {
16331679 ParseNtResult :: Tt ( tt) => ParseNtResult :: Tt ( tt) ,
1680+ ParseNtResult :: Vis ( x) => ParseNtResult :: Vis ( x) ,
16341681 ParseNtResult :: Nt ( nt) => ParseNtResult :: Nt ( f ( nt) ) ,
16351682 }
16361683 }
0 commit comments