@@ -34,6 +34,13 @@ impl<A: Array> ExpectOne<A> for SmallVec<A> {
3434}
3535
3636pub 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+
3744 // Methods in this trait have one of three forms:
3845 //
3946 // fn visit_t(&mut self, t: &mut T); // common
@@ -246,22 +253,6 @@ pub trait MutVisitor: Sized {
246253 noop_flat_map_generic_param ( param, self )
247254 }
248255
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-
265256 fn visit_param_bound ( & mut self , tpb : & mut GenericBound ) {
266257 noop_visit_param_bound ( tpb, self ) ;
267258 }
@@ -375,11 +366,30 @@ pub fn visit_mac_args<T: MutVisitor>(args: &mut MacArgs, vis: &mut T) {
375366 MacArgs :: Empty => { }
376367 MacArgs :: Delimited ( dspan, _delim, tokens) => {
377368 visit_delim_span ( dspan, vis) ;
378- vis . visit_tts ( tokens) ;
369+ visit_tts ( tokens, vis ) ;
379370 }
380371 MacArgs :: Eq ( eq_span, tokens) => {
381372 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+ }
383393 }
384394 }
385395}
@@ -626,28 +636,33 @@ pub fn noop_flat_map_param<T: MutVisitor>(mut param: Param, vis: &mut T) -> Smal
626636 smallvec ! [ param]
627637}
628638
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 ) {
630641 match tt {
631642 TokenTree :: Token ( token) => {
632- vis . visit_token ( token) ;
643+ visit_token ( token, vis ) ;
633644 }
634645 TokenTree :: Delimited ( DelimSpan { open, close } , _delim, tts) => {
635646 vis. visit_span ( open) ;
636647 vis. visit_span ( close) ;
637- vis . visit_tts ( tts) ;
648+ visit_tts ( tts, vis ) ;
638649 }
639650 }
640651}
641652
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+ }
645659}
646660
661+ // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
647662// Applies ident visitor if it's an ident; applies other visits to interpolated nodes.
648663// In practice the ident part is not actually used by specific visitors right now,
649664// 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 ) {
651666 let Token { kind, span } = t;
652667 match kind {
653668 token:: Ident ( name, _) | token:: Lifetime ( name) => {
@@ -659,13 +674,14 @@ pub fn noop_visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
659674 }
660675 token:: Interpolated ( nt) => {
661676 let mut nt = Lrc :: make_mut ( nt) ;
662- vis . visit_interpolated ( & mut nt) ;
677+ visit_interpolated ( & mut nt, vis ) ;
663678 }
664679 _ => { }
665680 }
666681 vis. visit_span ( span) ;
667682}
668683
684+ // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
669685/// Applies the visitor to elements of interpolated nodes.
670686//
671687// 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) {
689705// contain multiple items, but decided against it when I looked at
690706// `parse_item_or_view_item` and tried to figure out what I would do with
691707// 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 ) {
693709 match nt {
694710 token:: NtItem ( item) => visit_clobber ( item, |item| {
695711 // 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:
714730 visit_mac_args ( args, vis) ;
715731 }
716732 token:: NtPath ( path) => vis. visit_path ( path) ,
717- token:: NtTT ( tt) => vis . visit_tt ( tt) ,
733+ token:: NtTT ( tt) => visit_tt ( tt, vis ) ,
718734 token:: NtVis ( visib) => vis. visit_vis ( visib) ,
719735 }
720736}
0 commit comments