1919
2020use rustc_ast:: mut_visit:: { self , MutVisitor } ;
2121use rustc_ast:: ptr:: P ;
22+ use rustc_ast:: token:: { Nonterminal , Token , TokenKind } ;
23+ use rustc_ast:: tokenstream:: { TokenStream , TokenStreamBuilder , TokenTree } ;
2224use rustc_ast:: MacCall ;
2325use rustc_ast:: {
24- Expr , ExprKind , Item , ItemKind , Label , Pat , PatKind , Path , Stmt , StmtKind , Ty , TyKind ,
26+ Expr , ExprKind , Item , ItemKind , Label , MacArgs , Pat , PatKind , Path , Stmt , StmtKind , Ty , TyKind ,
2527} ;
28+ use rustc_data_structures:: sync:: Lrc ;
2629use rustc_parse:: parser:: { ForceCollect , Parser } ;
2730use rustc_span:: symbol:: Ident ;
2831use smallvec:: smallvec;
@@ -31,7 +34,7 @@ use smallvec::SmallVec;
3134use crate :: ast_manip:: util:: PatternSymbol ;
3235use crate :: ast_manip:: { AstNode , MutVisit } ;
3336use crate :: command:: CommandState ;
34- use crate :: matcher:: Bindings ;
37+ use crate :: matcher:: { BindingValue , Bindings } ;
3538use crate :: RefactorCtxt ;
3639
3740// `st` and `cx` were previously used for `def!` substitution, which has been removed. I expect
@@ -62,6 +65,39 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
6265 }
6366 }
6467 }
68+
69+ fn subst_tokenstream_bindings ( & mut self , ts : TokenStream ) -> TokenStream {
70+ let mut tsb = TokenStreamBuilder :: new ( ) ;
71+ let mut c = ts. into_trees ( ) ;
72+ while let Some ( tt) = c. next ( ) {
73+ if let TokenTree :: Token (
74+ Token {
75+ kind : TokenKind :: Ident ( ident, _is_raw) ,
76+ span,
77+ } ,
78+ spacing,
79+ ) = tt && let Some ( bv) = self . bindings . get :: < _ , BindingValue > ( ident) {
80+ let nt = match bv. clone ( ) {
81+ BindingValue :: Path ( x) => Nonterminal :: NtPath ( P ( x) ) ,
82+ BindingValue :: Expr ( x) => Nonterminal :: NtExpr ( x) ,
83+ BindingValue :: Pat ( x) => Nonterminal :: NtPat ( x) ,
84+ BindingValue :: Ty ( x) => Nonterminal :: NtTy ( x) ,
85+ BindingValue :: Stmt ( x) => Nonterminal :: NtStmt ( P ( x) ) ,
86+ BindingValue :: Item ( x) => Nonterminal :: NtItem ( x) ,
87+
88+ _ => unimplemented ! ( "Unsupported binding:{bv:#?}" )
89+ } ;
90+ let new_tt = TokenTree :: Token ( Token {
91+ kind : TokenKind :: Interpolated ( Lrc :: new ( nt) ) ,
92+ span,
93+ } , spacing) ;
94+ tsb. push ( TokenStream :: new ( vec ! [ new_tt] ) ) ;
95+ } else {
96+ tsb. push ( TokenStream :: new ( vec ! [ tt] ) ) ;
97+ }
98+ }
99+ tsb. build ( )
100+ }
65101}
66102
67103impl < ' a , ' tcx > MutVisitor for SubstFolder < ' a , ' tcx > {
@@ -235,6 +271,16 @@ impl<'a, 'tcx> MutVisitor for SubstFolder<'a, 'tcx> {
235271 }
236272
237273 fn visit_mac_call ( & mut self , mac : & mut MacCall ) {
274+ match * mac. args {
275+ MacArgs :: Empty => { }
276+ MacArgs :: Delimited ( _span, _delim, ref mut ts) => {
277+ * ts = self . subst_tokenstream_bindings ( std:: mem:: take ( ts) ) ;
278+ }
279+ MacArgs :: Eq ( _span, ref eq) => {
280+ log:: warn!( "Skipping substitution for MacArgsEq:{eq:#?}" ) ;
281+ }
282+ }
283+
238284 mut_visit:: noop_visit_mac ( mac, self )
239285 }
240286}
0 commit comments