@@ -400,7 +400,8 @@ fn push_fragment(buf: &mut Vec<tt::TokenTree>, fragment: Fragment) {
400
400
}
401
401
buf. push ( tt. into ( ) )
402
402
}
403
- Fragment :: Tokens ( tt) | Fragment :: Expr ( tt) => buf. push ( tt) ,
403
+ Fragment :: Path ( tt:: TokenTree :: Subtree ( tt) ) => fix_up_and_push_path_tt ( buf, tt) ,
404
+ Fragment :: Tokens ( tt) | Fragment :: Expr ( tt) | Fragment :: Path ( tt) => buf. push ( tt) ,
404
405
}
405
406
}
406
407
@@ -411,6 +412,45 @@ fn push_subtree(buf: &mut Vec<tt::TokenTree>, tt: tt::Subtree) {
411
412
}
412
413
}
413
414
415
+ /// Inserts the path separator `::` between an identifier and its following generic
416
+ /// argument list, and then pushes into the buffer. See [`Fragment::Path`] for why
417
+ /// we need this fixup.
418
+ fn fix_up_and_push_path_tt ( buf : & mut Vec < tt:: TokenTree > , subtree : tt:: Subtree ) {
419
+ stdx:: always!( matches!( subtree. delimiter. kind, tt:: DelimiterKind :: Invisible ) ) ;
420
+ let mut prev_was_ident = false ;
421
+ // Note that we only need to fix up the top-level `TokenTree`s because the
422
+ // context of the paths in the descendant `Subtree`s won't be changed by the
423
+ // mbe transcription.
424
+ for tt in subtree. token_trees {
425
+ if prev_was_ident {
426
+ // Pedantically, `(T) -> U` in `FnOnce(T) -> U` is treated as a generic
427
+ // argument list and thus needs `::` between it and `FnOnce`. However in
428
+ // today's Rust this type of path *semantically* cannot appear as a
429
+ // top-level expression-context path, so we can safely ignore it.
430
+ if let tt:: TokenTree :: Leaf ( tt:: Leaf :: Punct ( tt:: Punct { char : '<' , .. } ) ) = tt {
431
+ buf. push (
432
+ tt:: Leaf :: Punct ( tt:: Punct {
433
+ char : ':' ,
434
+ spacing : tt:: Spacing :: Joint ,
435
+ span : tt:: Span :: unspecified ( ) ,
436
+ } )
437
+ . into ( ) ,
438
+ ) ;
439
+ buf. push (
440
+ tt:: Leaf :: Punct ( tt:: Punct {
441
+ char : ':' ,
442
+ spacing : tt:: Spacing :: Alone ,
443
+ span : tt:: Span :: unspecified ( ) ,
444
+ } )
445
+ . into ( ) ,
446
+ ) ;
447
+ }
448
+ }
449
+ prev_was_ident = matches ! ( tt, tt:: TokenTree :: Leaf ( tt:: Leaf :: Ident ( _) ) ) ;
450
+ buf. push ( tt) ;
451
+ }
452
+ }
453
+
414
454
/// Handles `${count(t, depth)}`. `our_depth` is the recursion depth and `count_depth` is the depth
415
455
/// defined by the metavar expression.
416
456
fn count (
0 commit comments