@@ -103,6 +103,41 @@ macro_rules! maybe_whole {
103
103
} ;
104
104
}
105
105
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
+
106
141
/// If the next tokens are ill-formed `$ty::` recover them as `<$ty>::`.
107
142
#[ macro_export]
108
143
macro_rules! maybe_recover_from_interpolated_ty_qpath {
@@ -1423,7 +1458,15 @@ impl<'a> Parser<'a> {
1423
1458
/// so emit a proper diagnostic.
1424
1459
// Public for rustfmt usage.
1425
1460
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
+ }
1427
1470
1428
1471
if !self . eat_keyword ( kw:: Pub ) {
1429
1472
// We need a span for our `Spanned<VisibilityKind>`, but there's inherently no
@@ -1604,6 +1647,9 @@ pub enum FlatToken {
1604
1647
#[ derive( Clone , Debug ) ]
1605
1648
pub enum ParseNtResult < NtType > {
1606
1649
Tt ( TokenTree ) ,
1650
+ Vis ( P < ast:: Visibility > ) ,
1651
+
1652
+ /// This variant will eventually be removed, along with `Token::Interpolate`.
1607
1653
Nt ( NtType ) ,
1608
1654
}
1609
1655
@@ -1614,6 +1660,7 @@ impl<T> ParseNtResult<T> {
1614
1660
{
1615
1661
match self {
1616
1662
ParseNtResult :: Tt ( tt) => ParseNtResult :: Tt ( tt) ,
1663
+ ParseNtResult :: Vis ( x) => ParseNtResult :: Vis ( x) ,
1617
1664
ParseNtResult :: Nt ( nt) => ParseNtResult :: Nt ( f ( nt) ) ,
1618
1665
}
1619
1666
}
0 commit comments