@@ -3,7 +3,10 @@ use std::sync::Arc;
33
44use rustc_ast:: ExprKind ;
55use rustc_ast:: mut_visit:: { self , MutVisitor } ;
6- use rustc_ast:: token:: { self , Delimiter , IdentIsRaw , Lit , LitKind , Nonterminal , Token , TokenKind } ;
6+ use rustc_ast:: token:: {
7+ self , Delimiter , IdentIsRaw , InvisibleOrigin , Lit , LitKind , MetaVarKind , Nonterminal , Token ,
8+ TokenKind ,
9+ } ;
710use rustc_ast:: tokenstream:: { DelimSpacing , DelimSpan , Spacing , TokenStream , TokenTree } ;
811use rustc_data_structures:: fx:: FxHashMap ;
912use rustc_errors:: { Diag , DiagCtxtHandle , PResult , pluralize} ;
@@ -254,7 +257,6 @@ pub(super) fn transcribe<'a>(
254257 }
255258 }
256259
257- // Replace the meta-var with the matched token tree from the invocation.
258260 mbe:: TokenTree :: MetaVar ( mut sp, mut original_ident) => {
259261 // Find the matched nonterminal from the macro invocation, and use it to replace
260262 // the meta-var.
@@ -274,6 +276,33 @@ pub(super) fn transcribe<'a>(
274276 // some of the unnecessary whitespace.
275277 let ident = MacroRulesNormalizedIdent :: new ( original_ident) ;
276278 if let Some ( cur_matched) = lookup_cur_matched ( ident, interp, & repeats) {
279+ // We wrap the tokens in invisible delimiters, unless they are already wrapped
280+ // in invisible delimiters with the same `MetaVarKind`. Because there is no
281+ // point in having multiple layers of invisible delimiters of the same
282+ // `MetaVarKind`. Indeed, some proc macros can't handle them.
283+ let mut mk_delimited = |mv_kind, mut stream : TokenStream | {
284+ if stream. len ( ) == 1 {
285+ let tree = stream. iter ( ) . next ( ) . unwrap ( ) ;
286+ if let TokenTree :: Delimited ( _, _, delim, inner) = tree
287+ && let Delimiter :: Invisible ( InvisibleOrigin :: MetaVar ( mvk) ) = delim
288+ && mv_kind == * mvk
289+ {
290+ stream = inner. clone ( ) ;
291+ }
292+ }
293+
294+ // Emit as a token stream within `Delimiter::Invisible` to maintain
295+ // parsing priorities.
296+ marker. visit_span ( & mut sp) ;
297+ // Both the open delim and close delim get the same span, which covers the
298+ // `$foo` in the decl macro RHS.
299+ TokenTree :: Delimited (
300+ DelimSpan :: from_single ( sp) ,
301+ DelimSpacing :: new ( Spacing :: Alone , Spacing :: Alone ) ,
302+ Delimiter :: Invisible ( InvisibleOrigin :: MetaVar ( mv_kind) ) ,
303+ stream,
304+ )
305+ } ;
277306 let tt = match cur_matched {
278307 MatchedSingle ( ParseNtResult :: Tt ( tt) ) => {
279308 // `tt`s are emitted into the output stream directly as "raw tokens",
@@ -292,6 +321,9 @@ pub(super) fn transcribe<'a>(
292321 let kind = token:: NtLifetime ( * ident, * is_raw) ;
293322 TokenTree :: token_alone ( kind, sp)
294323 }
324+ MatchedSingle ( ParseNtResult :: Vis ( vis) ) => {
325+ mk_delimited ( MetaVarKind :: Vis , TokenStream :: from_ast ( vis) )
326+ }
295327 MatchedSingle ( ParseNtResult :: Nt ( nt) ) => {
296328 // Other variables are emitted into the output stream as groups with
297329 // `Delimiter::Invisible` to maintain parsing priorities.
0 commit comments