@@ -34,6 +34,13 @@ impl<A: Array> ExpectOne<A> for SmallVec<A> {
34
34
}
35
35
36
36
pub trait MutVisitor : Sized {
37
+ /// Mutable token visiting only exists for the `macro_rules` token marker and should not be
38
+ /// used otherwise. Token visitor would be entirely separate from the regular visitor if
39
+ /// the marker didn't have to visit AST fragments in nonterminal tokens.
40
+ fn token_visiting_enabled ( & self ) -> bool {
41
+ false
42
+ }
43
+
37
44
// Methods in this trait have one of three forms:
38
45
//
39
46
// fn visit_t(&mut self, t: &mut T); // common
@@ -246,22 +253,6 @@ pub trait MutVisitor: Sized {
246
253
noop_flat_map_generic_param ( param, self )
247
254
}
248
255
249
- fn visit_tt ( & mut self , tt : & mut TokenTree ) {
250
- noop_visit_tt ( tt, self ) ;
251
- }
252
-
253
- fn visit_tts ( & mut self , tts : & mut TokenStream ) {
254
- noop_visit_tts ( tts, self ) ;
255
- }
256
-
257
- fn visit_token ( & mut self , t : & mut Token ) {
258
- noop_visit_token ( t, self ) ;
259
- }
260
-
261
- fn visit_interpolated ( & mut self , nt : & mut token:: Nonterminal ) {
262
- noop_visit_interpolated ( nt, self ) ;
263
- }
264
-
265
256
fn visit_param_bound ( & mut self , tpb : & mut GenericBound ) {
266
257
noop_visit_param_bound ( tpb, self ) ;
267
258
}
@@ -375,11 +366,30 @@ pub fn visit_mac_args<T: MutVisitor>(args: &mut MacArgs, vis: &mut T) {
375
366
MacArgs :: Empty => { }
376
367
MacArgs :: Delimited ( dspan, _delim, tokens) => {
377
368
visit_delim_span ( dspan, vis) ;
378
- vis . visit_tts ( tokens) ;
369
+ visit_tts ( tokens, vis ) ;
379
370
}
380
371
MacArgs :: Eq ( eq_span, tokens) => {
381
372
vis. visit_span ( eq_span) ;
382
- vis. visit_tts ( tokens) ;
373
+ visit_tts ( tokens, vis) ;
374
+ // The value in `#[key = VALUE]` must be visited as an expression for backward
375
+ // compatibility, so that macros can be expanded in that position.
376
+ if !vis. token_visiting_enabled ( ) {
377
+ if let Some ( TokenTree :: Token ( token) ) = tokens. trees_ref ( ) . next ( ) {
378
+ if let token:: Interpolated ( ..) = token. kind {
379
+ // ^^ Do not `make_mut` unless we have to.
380
+ match Lrc :: make_mut ( & mut tokens. 0 ) . get_mut ( 0 ) {
381
+ Some ( ( TokenTree :: Token ( token) , _spacing) ) => match & mut token. kind {
382
+ token:: Interpolated ( nt) => match Lrc :: make_mut ( nt) {
383
+ token:: NtExpr ( expr) => vis. visit_expr ( expr) ,
384
+ t => panic ! ( "unexpected token in key-value attribute: {:?}" , t) ,
385
+ } ,
386
+ t => panic ! ( "unexpected token in key-value attribute: {:?}" , t) ,
387
+ } ,
388
+ t => panic ! ( "unexpected token in key-value attribute: {:?}" , t) ,
389
+ }
390
+ }
391
+ }
392
+ }
383
393
}
384
394
}
385
395
}
@@ -626,28 +636,33 @@ pub fn noop_flat_map_param<T: MutVisitor>(mut param: Param, vis: &mut T) -> Smal
626
636
smallvec ! [ param]
627
637
}
628
638
629
- pub fn noop_visit_tt < T : MutVisitor > ( tt : & mut TokenTree , vis : & mut T ) {
639
+ // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
640
+ pub fn visit_tt < T : MutVisitor > ( tt : & mut TokenTree , vis : & mut T ) {
630
641
match tt {
631
642
TokenTree :: Token ( token) => {
632
- vis . visit_token ( token) ;
643
+ visit_token ( token, vis ) ;
633
644
}
634
645
TokenTree :: Delimited ( DelimSpan { open, close } , _delim, tts) => {
635
646
vis. visit_span ( open) ;
636
647
vis. visit_span ( close) ;
637
- vis . visit_tts ( tts) ;
648
+ visit_tts ( tts, vis ) ;
638
649
}
639
650
}
640
651
}
641
652
642
- pub fn noop_visit_tts < T : MutVisitor > ( TokenStream ( tts) : & mut TokenStream , vis : & mut T ) {
643
- let tts = Lrc :: make_mut ( tts) ;
644
- visit_vec ( tts, |( tree, _is_joint) | vis. visit_tt ( tree) ) ;
653
+ // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
654
+ pub fn visit_tts < T : MutVisitor > ( TokenStream ( tts) : & mut TokenStream , vis : & mut T ) {
655
+ if vis. token_visiting_enabled ( ) {
656
+ let tts = Lrc :: make_mut ( tts) ;
657
+ visit_vec ( tts, |( tree, _is_joint) | visit_tt ( tree, vis) ) ;
658
+ }
645
659
}
646
660
661
+ // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
647
662
// Applies ident visitor if it's an ident; applies other visits to interpolated nodes.
648
663
// In practice the ident part is not actually used by specific visitors right now,
649
664
// but there's a test below checking that it works.
650
- pub fn noop_visit_token < T : MutVisitor > ( t : & mut Token , vis : & mut T ) {
665
+ pub fn visit_token < T : MutVisitor > ( t : & mut Token , vis : & mut T ) {
651
666
let Token { kind, span } = t;
652
667
match kind {
653
668
token:: Ident ( name, _) | token:: Lifetime ( name) => {
@@ -659,13 +674,14 @@ pub fn noop_visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
659
674
}
660
675
token:: Interpolated ( nt) => {
661
676
let mut nt = Lrc :: make_mut ( nt) ;
662
- vis . visit_interpolated ( & mut nt) ;
677
+ visit_interpolated ( & mut nt, vis ) ;
663
678
}
664
679
_ => { }
665
680
}
666
681
vis. visit_span ( span) ;
667
682
}
668
683
684
+ // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
669
685
/// Applies the visitor to elements of interpolated nodes.
670
686
//
671
687
// N.B., this can occur only when applying a visitor to partially expanded
@@ -689,7 +705,7 @@ pub fn noop_visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
689
705
// contain multiple items, but decided against it when I looked at
690
706
// `parse_item_or_view_item` and tried to figure out what I would do with
691
707
// multiple items there....
692
- pub fn noop_visit_interpolated < T : MutVisitor > ( nt : & mut token:: Nonterminal , vis : & mut T ) {
708
+ pub fn visit_interpolated < T : MutVisitor > ( nt : & mut token:: Nonterminal , vis : & mut T ) {
693
709
match nt {
694
710
token:: NtItem ( item) => visit_clobber ( item, |item| {
695
711
// This is probably okay, because the only visitors likely to
@@ -714,7 +730,7 @@ pub fn noop_visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis:
714
730
visit_mac_args ( args, vis) ;
715
731
}
716
732
token:: NtPath ( path) => vis. visit_path ( path) ,
717
- token:: NtTT ( tt) => vis . visit_tt ( tt) ,
733
+ token:: NtTT ( tt) => visit_tt ( tt, vis ) ,
718
734
token:: NtVis ( visib) => vis. visit_vis ( visib) ,
719
735
}
720
736
}
0 commit comments