@@ -17,6 +17,11 @@ struct AstSubsts {
17
17
lifetimes : Vec < ast:: LifetimeArg > ,
18
18
}
19
19
20
+ struct TypeOrConstSubst {
21
+ subst : ast:: Type ,
22
+ to_be_transformed : bool ,
23
+ }
24
+
20
25
type LifetimeName = String ;
21
26
22
27
/// `PathTransform` substitutes path in SyntaxNodes in bulk.
@@ -123,13 +128,21 @@ impl<'a> PathTransform<'a> {
123
128
// the resulting change can be applied correctly.
124
129
. zip ( self . substs . types_and_consts . iter ( ) . map ( Some ) . chain ( std:: iter:: repeat ( None ) ) )
125
130
. 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
+ }
127
136
( Either :: Right ( t) , None ) => {
128
137
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) )
133
146
}
134
147
( Either :: Left ( _) , None ) => None , // FIXME: get default const value
135
148
} )
@@ -151,45 +164,44 @@ impl<'a> PathTransform<'a> {
151
164
}
152
165
153
166
struct Ctx < ' a > {
154
- type_and_const_substs : FxHashMap < hir:: TypeOrConstParam , ast :: Type > ,
167
+ type_and_const_substs : FxHashMap < hir:: TypeOrConstParam , TypeOrConstSubst > ,
155
168
lifetime_substs : FxHashMap < LifetimeName , ast:: Lifetime > ,
156
169
target_module : hir:: Module ,
157
170
source_scope : & ' a SemanticsScope < ' a > ,
158
171
}
159
172
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
+
160
180
impl < ' a > Ctx < ' a > {
161
181
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
+
162
192
// `transform_path` may update a node's parent and that would break the
163
193
// tree traversal. Thus all paths in the tree are collected into a vec
164
194
// 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 < _ > > ( ) ;
174
196
for path in paths {
175
197
self . transform_path ( path) ;
176
198
}
177
199
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
+ } ) ;
193
205
}
194
206
195
207
fn transform_path ( & self , path : ast:: Path ) -> Option < ( ) > {
@@ -208,7 +220,9 @@ impl<'a> Ctx<'a> {
208
220
209
221
match resolution {
210
222
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
+ {
212
226
let parent = path. syntax ( ) . parent ( ) ?;
213
227
if let Some ( parent) = ast:: Path :: cast ( parent. clone ( ) ) {
214
228
// Path inside path means that there is an associated
@@ -276,7 +290,9 @@ impl<'a> Ctx<'a> {
276
290
ted:: replace ( path. syntax ( ) , res. syntax ( ) )
277
291
}
278
292
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
+ {
280
296
ted:: replace ( path. syntax ( ) , subst. clone_subtree ( ) . clone_for_update ( ) . syntax ( ) ) ;
281
297
}
282
298
}
0 commit comments