@@ -274,11 +274,6 @@ pub(super) fn transcribe<'a>(
274
274
// without wrapping them into groups.
275
275
maybe_use_metavar_location ( psess, & stack, sp, tt, & mut marker)
276
276
}
277
- MatchedSingle ( ParseNtResult :: Ident ( ident, is_raw) ) => {
278
- marker. visit_span ( & mut sp) ;
279
- let kind = token:: NtIdent ( * ident, * is_raw) ;
280
- TokenTree :: token_alone ( kind, sp)
281
- }
282
277
MatchedSingle ( ParseNtResult :: Lifetime ( ident) ) => {
283
278
marker. visit_span ( & mut sp) ;
284
279
let kind = token:: NtLifetime ( * ident) ;
@@ -395,9 +390,22 @@ fn maybe_use_metavar_location(
395
390
return orig_tt. clone ( ) ;
396
391
}
397
392
398
- let insert = |mspans : & mut FxHashMap < _ , _ > , s, ms| match mspans. try_insert ( s, ms) {
393
+ let insert = |mspans : & mut FxHashMap < _ , _ > , s, ms : Span | match mspans. try_insert ( s, ms) {
399
394
Ok ( _) => true ,
400
- Err ( err) => * err. entry . get ( ) == ms, // Tried to insert the same span, still success
395
+ Err ( mut err) => {
396
+ let old_ms = * err. entry . get ( ) ;
397
+ if ms == old_ms {
398
+ // Tried to insert the same span, still success.
399
+ return true ;
400
+ }
401
+ if !ms. eq_ctxt ( old_ms) && ms. ctxt ( ) . outer_expn_data ( ) . call_site . eq_ctxt ( old_ms) {
402
+ // This looks like a variable passed to an inner (possibly recursive) macro call.
403
+ // The innermost metavar span is the most useful, so override.
404
+ err. entry . insert ( ms) ;
405
+ return true ;
406
+ }
407
+ false
408
+ }
401
409
} ;
402
410
marker. visit_span ( & mut metavar_span) ;
403
411
let no_collision = match orig_tt {
@@ -411,16 +419,23 @@ fn maybe_use_metavar_location(
411
419
} ) ,
412
420
} ;
413
421
if no_collision || psess. source_map ( ) . is_imported ( metavar_span) {
422
+ // Add a whitespace for backward compatibility.
423
+ // FIXME: assign spacing to tokens from metavars in a more systematic way (#127123).
424
+ if let TokenTree :: Token ( token, _) = orig_tt {
425
+ return TokenTree :: Token ( token. clone ( ) , Spacing :: Alone ) ;
426
+ }
414
427
return orig_tt. clone ( ) ;
415
428
}
416
429
417
430
// Setting metavar spans for the heuristic spans gives better opportunities for combining them
418
431
// with neighboring spans even despite their different syntactic contexts.
419
432
match orig_tt {
420
- TokenTree :: Token ( Token { kind, span } , spacing ) => {
433
+ TokenTree :: Token ( Token { kind, span } , _spacing ) => {
421
434
let span = metavar_span. with_ctxt ( span. ctxt ( ) ) ;
422
435
with_metavar_spans ( |mspans| insert ( mspans, span, metavar_span) ) ;
423
- TokenTree :: Token ( Token { kind : kind. clone ( ) , span } , * spacing)
436
+ // Add a whitespace for backward compatibility.
437
+ // FIXME: assign spacing to tokens from metavars in a more systematic way (#127123).
438
+ TokenTree :: Token ( Token { kind : kind. clone ( ) , span } , Spacing :: Alone )
424
439
}
425
440
TokenTree :: Delimited ( dspan, dspacing, delimiter, tts) => {
426
441
let open = metavar_span. with_ctxt ( dspan. open . ctxt ( ) ) ;
@@ -735,12 +750,6 @@ fn extract_ident<'a>(
735
750
interp : & FxHashMap < MacroRulesNormalizedIdent , NamedMatch > ,
736
751
) -> PResult < ' a , String > {
737
752
if let NamedMatch :: MatchedSingle ( pnr) = matched_from_ident ( dcx, ident, interp) ? {
738
- if let ParseNtResult :: Ident ( nt_ident, is_raw) = pnr {
739
- if let IdentIsRaw :: Yes = is_raw {
740
- return Err ( dcx. struct_span_err ( ident. span , RAW_IDENT_ERR ) ) ;
741
- }
742
- return Ok ( nt_ident. to_string ( ) ) ;
743
- }
744
753
if let ParseNtResult :: Tt ( TokenTree :: Token (
745
754
Token { kind : TokenKind :: Ident ( token_ident, is_raw) , .. } ,
746
755
_,
0 commit comments