@@ -21,22 +21,61 @@ use crate::ast_manip::MutVisit;
2121/// causes problems for us later on.  This folder detects nodes like `&foo` and gives them a 
2222/// macro-generated span to fix the problem. 
2323struct  FixFormat  { 
24+     ctxt :  FormatCtxt , 
25+ } 
26+ 
27+ #[ derive( Clone ) ]  
28+ struct  FormatCtxt  { 
2429    /// The span of the most recent ancestor `Expr`. 
2530parent_span :  Span , 
2631    /// Are we currently inside (the macro-generated part of) a `format!` invocation? 
2732in_format :  bool , 
33+     /// Are we currently inside the match in (the macro-generated part of) a 
34+ /// `format!` invocation? 
35+ in_match :  bool , 
36+ } 
37+ 
38+ impl  FormatCtxt  { 
39+     fn  new ( span :  Span )  -> Self  { 
40+         FormatCtxt  { 
41+             parent_span :  span, 
42+             in_format :  false , 
43+             in_match :  false , 
44+         } 
45+     } 
46+ 
47+     fn  enter_span ( & self ,  span :  Span )  -> Self  { 
48+         FormatCtxt  { 
49+             parent_span :  span, 
50+             ..* self 
51+         } 
52+     } 
53+ 
54+     fn  enter_format ( & self ,  span :  Span )  -> Self  { 
55+         FormatCtxt  { 
56+             parent_span :  span, 
57+             in_format :  true , 
58+             ..* self 
59+         } 
60+     } 
61+ 
62+     fn  enter_match ( & self ,  span :  Span )  -> Self  { 
63+         FormatCtxt  { 
64+             parent_span :  span, 
65+             in_match :  true , 
66+             ..* self 
67+         } 
68+     } 
2869} 
2970
3071impl  FixFormat  { 
31-     fn  descend < F ,  R > ( & mut  self ,  in_format :   bool ,   cur_span :   Span ,  f :  F )  -> R 
72+     fn  descend < F ,  R > ( & mut  self ,  new_ctxt :   FormatCtxt ,  f :  F )  -> R 
3273    where 
3374        F :  FnOnce ( & mut  Self )  -> R , 
3475    { 
35-         let  old_in_format = mem:: replace ( & mut  self . in_format ,  in_format) ; 
36-         let  old_parent_span = mem:: replace ( & mut  self . parent_span ,  cur_span) ; 
76+         let  old_ctxt = mem:: replace ( & mut  self . ctxt ,  new_ctxt) ; 
3777        let  r = f ( self ) ; 
38-         self . in_format  = old_in_format; 
39-         self . parent_span  = old_parent_span; 
78+         self . ctxt  = old_ctxt; 
4079        r
4180    } 
4281
@@ -48,40 +87,62 @@ impl FixFormat {
4887        // recognize it by its span: it's macro-generated, but the "macro definition" actually 
4988        // points to the format string, which lies inside the macro invocation itself. 
5089
51-         if  !matches ! ( [ e . node ]   ExprKind :: Match ( .. ) )  { 
90+         if  !e . span . from_expansion ( )  { 
5291            return  false ; 
5392        } 
5493
55-         if  !e. span . from_expansion ( )  { 
56-             return  false ; 
94+         if  let  ExprKind :: Call ( callee,  _)  = & e. node  { 
95+             if  let  ExprKind :: Path ( None ,  path)  = & callee. node  { 
96+                 let  matches_fmt_args = path. segments . len ( )  == 4  &&
97+                     path. segments [ 1 ] . ident . as_str ( )  == "fmt"  &&
98+                     path. segments [ 2 ] . ident . as_str ( )  == "Arguments"  &&
99+                     ( path. segments [ 3 ] . ident . as_str ( )  == "new_v1"  ||
100+                      path. segments [ 3 ] . ident . as_str ( )  == "new_v1_formatted" ) ; 
101+                 return  matches_fmt_args; 
102+             } 
57103        } 
58104
59-         e . span . source_callsite ( ) . contains ( e . span ) 
105+         false 
60106    } 
61107} 
62108
63109impl  MutVisitor  for  FixFormat  { 
64110    fn  visit_expr ( & mut  self ,  e :  & mut  P < Expr > )  { 
65-         if  self . in_format 
66-             && !e . span . from_expansion ( ) 
111+         if  !e . span . from_expansion ( ) 
112+             && self . ctxt . in_match 
67113            && matches ! ( [ e. node]  ExprKind :: AddrOf ( ..) ) 
68114        { 
69115            trace ! ( "EXITING format! at {:?}" ,  e) ; 
70-             // Current node is the `&foo`.  We need to change its span.  On recursing into `foo`, 
71-             // we are no longer inside a `format!` invocation. 
72-             let  new_span = self . parent_span ; 
73-             self . descend ( false ,  e. span ,  |this| { 
116+             // Current node is the `&foo`.  We need to change its span.  On 
117+             // recursing into `foo`, we are no longer inside a `format!` 
118+             // invocation. 
119+             let  mac_span = self . ctxt . parent_span ; 
120+             let  leave_ctxt = FormatCtxt :: new ( e. span ) ; 
121+             self . descend ( leave_ctxt,  |this| { 
74122                mut_visit:: noop_visit_expr ( e,  this) ; 
75-                 e. span  = new_span ; 
123+                 e. span  = mac_span ; 
76124            } ) 
77-         }  else  if  !self . in_format  && self . is_format_entry ( & e)  { 
125+         }  else  if  !e. span . from_expansion ( ) 
126+             && self . ctxt . in_format 
127+             && !self . ctxt . in_match 
128+         { 
129+             trace ! ( "Fixing format! string at {:?}" ,  e) ; 
130+             let  mac_span = self . ctxt . parent_span ; 
131+             let  new_ctxt = self . ctxt . enter_span ( mac_span) ; 
132+             self . descend ( new_ctxt,  |this| { 
133+                 mut_visit:: noop_visit_expr ( e,  this) ; 
134+                 e. span  = mac_span; 
135+             } ) 
136+         }  else  if  self . ctxt . in_format  && matches ! ( [ e. node]  ExprKind :: Match ( ..) )  { 
137+             let  new_ctxt = self . ctxt . enter_match ( e. span ) ; 
138+             self . descend ( new_ctxt,  |this| mut_visit:: noop_visit_expr ( e,  this) ) 
139+         }  else  if  !self . ctxt . in_format  && self . is_format_entry ( & e)  { 
78140            trace ! ( "ENTERING format! at {:?}" ,  e) ; 
79-             self . descend ( true ,  e. span ,  |this| mut_visit:: noop_visit_expr ( e,  this) ) 
141+             let  new_ctxt = self . ctxt . enter_format ( e. span ) ; 
142+             self . descend ( new_ctxt,  |this| mut_visit:: noop_visit_expr ( e,  this) ) 
80143        }  else  { 
81-             let  in_format = self . in_format ; 
82-             self . descend ( in_format,  e. span ,  |this| { 
83-                 mut_visit:: noop_visit_expr ( e,  this) 
84-             } ) 
144+             let  new_ctxt = self . ctxt . enter_span ( e. span ) ; 
145+             self . descend ( new_ctxt,  |this| mut_visit:: noop_visit_expr ( e,  this) ) 
85146        } 
86147    } 
87148
@@ -129,8 +190,7 @@ impl MutVisitor for FixAttrs {
129190#[ cfg_attr( feature = "profile" ,  flame) ]  
130191pub  fn  fix_format < T :  MutVisit > ( node :  & mut  T )  { 
131192    let  mut  fix_format = FixFormat  { 
132-         parent_span :  DUMMY_SP , 
133-         in_format :  false , 
193+         ctxt :  FormatCtxt :: new ( DUMMY_SP ) , 
134194    } ; 
135195    node. visit ( & mut  fix_format) 
136196} 
0 commit comments