@@ -17,6 +17,11 @@ struct AstSubsts {
1717 lifetimes : Vec < ast:: LifetimeArg > ,
1818}
1919
20+ struct TypeOrConstSubst {
21+ subst : ast:: Type ,
22+ to_be_transformed : bool ,
23+ }
24+
2025type LifetimeName = String ;
2126
2227/// `PathTransform` substitutes path in SyntaxNodes in bulk.
@@ -123,13 +128,21 @@ impl<'a> PathTransform<'a> {
123128 // the resulting change can be applied correctly.
124129 . zip ( self . substs . types_and_consts . iter ( ) . map ( Some ) . chain ( std:: iter:: repeat ( None ) ) )
125130 . filter_map ( |( k, v) | match ( k. split ( db) , v) {
126- ( _, Some ( v) ) => Some ( ( k, v. ty ( ) ?. clone ( ) ) ) ,
131+ ( _, Some ( v) ) => {
132+ let subst =
133+ TypeOrConstSubst { subst : v. ty ( ) ?. clone ( ) , to_be_transformed : false } ;
134+ Some ( ( k, subst) )
135+ }
127136 ( Either :: Right ( t) , None ) => {
128137 let default = t. default ( db) ?;
129- let v = ast:: make:: ty (
130- & default. display_source_code ( db, source_module. into ( ) , false ) . ok ( ) ?,
131- ) ;
132- Some ( ( k, v) )
138+ let subst = TypeOrConstSubst {
139+ subst : ast:: make:: ty (
140+ & default. display_source_code ( db, source_module. into ( ) , false ) . ok ( ) ?,
141+ )
142+ . clone_for_update ( ) ,
143+ to_be_transformed : true ,
144+ } ;
145+ Some ( ( k, subst) )
133146 }
134147 ( Either :: Left ( _) , None ) => None , // FIXME: get default const value
135148 } )
@@ -151,45 +164,44 @@ impl<'a> PathTransform<'a> {
151164}
152165
153166struct Ctx < ' a > {
154- type_and_const_substs : FxHashMap < hir:: TypeOrConstParam , ast :: Type > ,
167+ type_and_const_substs : FxHashMap < hir:: TypeOrConstParam , TypeOrConstSubst > ,
155168 lifetime_substs : FxHashMap < LifetimeName , ast:: Lifetime > ,
156169 target_module : hir:: Module ,
157170 source_scope : & ' a SemanticsScope < ' a > ,
158171}
159172
173+ fn preorder ( item : & SyntaxNode ) -> impl Iterator < Item = SyntaxNode > {
174+ item. preorder ( ) . filter_map ( |event| match event {
175+ syntax:: WalkEvent :: Enter ( _) => None ,
176+ syntax:: WalkEvent :: Leave ( node) => Some ( node) ,
177+ } )
178+ }
179+
160180impl < ' a > Ctx < ' a > {
161181 fn apply ( & self , item : & SyntaxNode ) {
182+ for ( _, subst) in & self . type_and_const_substs {
183+ if subst. to_be_transformed {
184+ let paths =
185+ preorder ( & subst. subst . syntax ( ) ) . filter_map ( ast:: Path :: cast) . collect :: < Vec < _ > > ( ) ;
186+ for path in paths {
187+ self . transform_path ( path) ;
188+ }
189+ }
190+ }
191+
162192 // `transform_path` may update a node's parent and that would break the
163193 // tree traversal. Thus all paths in the tree are collected into a vec
164194 // so that such operation is safe.
165- let paths = item
166- . preorder ( )
167- . filter_map ( |event| match event {
168- syntax:: WalkEvent :: Enter ( _) => None ,
169- syntax:: WalkEvent :: Leave ( node) => Some ( node) ,
170- } )
171- . filter_map ( ast:: Path :: cast)
172- . collect :: < Vec < _ > > ( ) ;
173-
195+ let paths = preorder ( item) . filter_map ( ast:: Path :: cast) . collect :: < Vec < _ > > ( ) ;
174196 for path in paths {
175197 self . transform_path ( path) ;
176198 }
177199
178- item. preorder ( )
179- . filter_map ( |event| match event {
180- syntax:: WalkEvent :: Enter ( _) => None ,
181- syntax:: WalkEvent :: Leave ( node) => Some ( node) ,
182- } )
183- . filter_map ( ast:: Lifetime :: cast)
184- . for_each ( |lifetime| {
185- if let Some ( subst) = self . lifetime_substs . get ( & lifetime. syntax ( ) . text ( ) . to_string ( ) )
186- {
187- ted:: replace (
188- lifetime. syntax ( ) ,
189- subst. clone_subtree ( ) . clone_for_update ( ) . syntax ( ) ,
190- ) ;
191- }
192- } ) ;
200+ preorder ( item) . filter_map ( ast:: Lifetime :: cast) . for_each ( |lifetime| {
201+ if let Some ( subst) = self . lifetime_substs . get ( & lifetime. syntax ( ) . text ( ) . to_string ( ) ) {
202+ ted:: replace ( lifetime. syntax ( ) , subst. clone_subtree ( ) . clone_for_update ( ) . syntax ( ) ) ;
203+ }
204+ } ) ;
193205 }
194206
195207 fn transform_path ( & self , path : ast:: Path ) -> Option < ( ) > {
@@ -208,7 +220,9 @@ impl<'a> Ctx<'a> {
208220
209221 match resolution {
210222 hir:: PathResolution :: TypeParam ( tp) => {
211- if let Some ( subst) = self . type_and_const_substs . get ( & tp. merge ( ) ) {
223+ if let Some ( TypeOrConstSubst { subst, .. } ) =
224+ self . type_and_const_substs . get ( & tp. merge ( ) )
225+ {
212226 let parent = path. syntax ( ) . parent ( ) ?;
213227 if let Some ( parent) = ast:: Path :: cast ( parent. clone ( ) ) {
214228 // Path inside path means that there is an associated
@@ -276,7 +290,9 @@ impl<'a> Ctx<'a> {
276290 ted:: replace ( path. syntax ( ) , res. syntax ( ) )
277291 }
278292 hir:: PathResolution :: ConstParam ( cp) => {
279- if let Some ( subst) = self . type_and_const_substs . get ( & cp. merge ( ) ) {
293+ if let Some ( TypeOrConstSubst { subst, .. } ) =
294+ self . type_and_const_substs . get ( & cp. merge ( ) )
295+ {
280296 ted:: replace ( path. syntax ( ) , subst. clone_subtree ( ) . clone_for_update ( ) . syntax ( ) ) ;
281297 }
282298 }
0 commit comments