@@ -104,6 +104,41 @@ macro_rules! maybe_whole {
104
104
} ;
105
105
}
106
106
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
+
107
142
/// If the next tokens are ill-formed `$ty::` recover them as `<$ty>::`.
108
143
#[ macro_export]
109
144
macro_rules! maybe_recover_from_interpolated_ty_qpath {
@@ -1440,7 +1475,15 @@ impl<'a> Parser<'a> {
1440
1475
/// so emit a proper diagnostic.
1441
1476
// Public for rustfmt usage.
1442
1477
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
+ }
1444
1487
1445
1488
if !self . eat_keyword ( kw:: Pub ) {
1446
1489
// We need a span for our `Spanned<VisibilityKind>`, but there's inherently no
@@ -1621,6 +1664,9 @@ pub enum FlatToken {
1621
1664
#[ derive( Clone , Debug ) ]
1622
1665
pub enum ParseNtResult < NtType > {
1623
1666
Tt ( TokenTree ) ,
1667
+ Vis ( P < ast:: Visibility > ) ,
1668
+
1669
+ /// This variant will eventually be removed, along with `Token::Interpolate`.
1624
1670
Nt ( NtType ) ,
1625
1671
}
1626
1672
@@ -1631,6 +1677,7 @@ impl<T> ParseNtResult<T> {
1631
1677
{
1632
1678
match self {
1633
1679
ParseNtResult :: Tt ( tt) => ParseNtResult :: Tt ( tt) ,
1680
+ ParseNtResult :: Vis ( x) => ParseNtResult :: Vis ( x) ,
1634
1681
ParseNtResult :: Nt ( nt) => ParseNtResult :: Nt ( f ( nt) ) ,
1635
1682
}
1636
1683
}
0 commit comments