@@ -17,11 +17,6 @@ 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
-
25
20
type LifetimeName = String ;
26
21
27
22
/// `PathTransform` substitutes path in SyntaxNodes in bulk.
@@ -115,8 +110,10 @@ impl<'a> PathTransform<'a> {
115
110
Some ( hir:: GenericDef :: Trait ( _) ) => 1 ,
116
111
_ => 0 ,
117
112
} ;
118
- let type_and_const_substs: FxHashMap < _ , _ > = self
119
- . generic_def
113
+ let mut type_substs: FxHashMap < hir:: TypeParam , ast:: Type > = Default :: default ( ) ;
114
+ let mut const_substs: FxHashMap < hir:: ConstParam , SyntaxNode > = Default :: default ( ) ;
115
+ let mut default_types: Vec < hir:: TypeParam > = Default :: default ( ) ;
116
+ self . generic_def
120
117
. into_iter ( )
121
118
. flat_map ( |it| it. type_params ( db) )
122
119
. skip ( skip)
@@ -127,50 +124,57 @@ impl<'a> PathTransform<'a> {
127
124
// a default type. If they do, go for that type from `hir` to `ast` so
128
125
// the resulting change can be applied correctly.
129
126
. zip ( self . substs . types_and_consts . iter ( ) . map ( Some ) . chain ( std:: iter:: repeat ( None ) ) )
130
- . filter_map ( |( k, v) | match ( k. split ( db) , v) {
131
- ( _ , Some ( v) ) => {
132
- let subst =
133
- TypeOrConstSubst { subst : v . ty ( ) ? . clone ( ) , to_be_transformed : false } ;
134
- Some ( ( k , subst ) )
127
+ . for_each ( |( k, v) | match ( k. split ( db) , v) {
128
+ ( Either :: Right ( t ) , Some ( v) ) => {
129
+ if let Some ( ty ) = v . ty ( ) {
130
+ type_substs . insert ( t , ty . clone ( ) ) ;
131
+ }
135
132
}
136
133
( Either :: Right ( t) , None ) => {
137
- let default = t. default ( db) ?;
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) )
134
+ if let Some ( default) = t. default ( db) {
135
+ if let Some ( default) =
136
+ & default. display_source_code ( db, source_module. into ( ) , false ) . ok ( )
137
+ {
138
+ type_substs. insert ( t, ast:: make:: ty ( default) . clone_for_update ( ) ) ;
139
+ default_types. push ( t) ;
140
+ }
141
+ }
146
142
}
147
- ( Either :: Left ( _) , None ) => None , // FIXME: get default const value
148
- } )
149
- . collect ( ) ;
143
+ ( Either :: Left ( c) , Some ( v) ) => {
144
+ if let Some ( ty) = v. ty ( ) {
145
+ const_substs. insert ( c, ty. syntax ( ) . clone ( ) ) ;
146
+ }
147
+ }
148
+ ( Either :: Left ( _) , None ) => ( ) , // FIXME: get default const value
149
+ } ) ;
150
150
let lifetime_substs: FxHashMap < _ , _ > = self
151
151
. generic_def
152
152
. into_iter ( )
153
153
. flat_map ( |it| it. lifetime_params ( db) )
154
154
. zip ( self . substs . lifetimes . clone ( ) )
155
155
. filter_map ( |( k, v) | Some ( ( k. name ( db) . display ( db. upcast ( ) ) . to_string ( ) , v. lifetime ( ) ?) ) )
156
156
. collect ( ) ;
157
- Ctx {
158
- type_and_const_substs,
157
+ let ctx = Ctx {
158
+ type_substs,
159
+ const_substs,
159
160
lifetime_substs,
160
161
target_module,
161
162
source_scope : self . source_scope ,
162
- }
163
+ } ;
164
+ ctx. transform_default_type_substs ( default_types) ;
165
+ ctx
163
166
}
164
167
}
165
168
166
169
struct Ctx < ' a > {
167
- type_and_const_substs : FxHashMap < hir:: TypeOrConstParam , TypeOrConstSubst > ,
170
+ type_substs : FxHashMap < hir:: TypeParam , ast:: Type > ,
171
+ const_substs : FxHashMap < hir:: ConstParam , SyntaxNode > ,
168
172
lifetime_substs : FxHashMap < LifetimeName , ast:: Lifetime > ,
169
173
target_module : hir:: Module ,
170
174
source_scope : & ' a SemanticsScope < ' a > ,
171
175
}
172
176
173
- fn preorder ( item : & SyntaxNode ) -> impl Iterator < Item = SyntaxNode > {
177
+ fn postorder ( item : & SyntaxNode ) -> impl Iterator < Item = SyntaxNode > {
174
178
item. preorder ( ) . filter_map ( |event| match event {
175
179
syntax:: WalkEvent :: Enter ( _) => None ,
176
180
syntax:: WalkEvent :: Leave ( node) => Some ( node) ,
@@ -179,31 +183,31 @@ fn preorder(item: &SyntaxNode) -> impl Iterator<Item = SyntaxNode> {
179
183
180
184
impl < ' a > Ctx < ' a > {
181
185
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
-
192
186
// `transform_path` may update a node's parent and that would break the
193
187
// tree traversal. Thus all paths in the tree are collected into a vec
194
188
// so that such operation is safe.
195
- let paths = preorder ( item) . filter_map ( ast:: Path :: cast) . collect :: < Vec < _ > > ( ) ;
189
+ let paths = postorder ( item) . filter_map ( ast:: Path :: cast) . collect :: < Vec < _ > > ( ) ;
196
190
for path in paths {
197
191
self . transform_path ( path) ;
198
192
}
199
193
200
- preorder ( item) . filter_map ( ast:: Lifetime :: cast) . for_each ( |lifetime| {
194
+ postorder ( item) . filter_map ( ast:: Lifetime :: cast) . for_each ( |lifetime| {
201
195
if let Some ( subst) = self . lifetime_substs . get ( & lifetime. syntax ( ) . text ( ) . to_string ( ) ) {
202
196
ted:: replace ( lifetime. syntax ( ) , subst. clone_subtree ( ) . clone_for_update ( ) . syntax ( ) ) ;
203
197
}
204
198
} ) ;
205
199
}
206
200
201
+ fn transform_default_type_substs ( & self , default_types : Vec < hir:: TypeParam > ) {
202
+ for k in default_types {
203
+ let v = self . type_substs . get ( & k) . unwrap ( ) ;
204
+ let paths = postorder ( & v. syntax ( ) ) . filter_map ( ast:: Path :: cast) . collect :: < Vec < _ > > ( ) ;
205
+ for path in paths {
206
+ self . transform_path ( path) ;
207
+ }
208
+ }
209
+ }
210
+
207
211
fn transform_path ( & self , path : ast:: Path ) -> Option < ( ) > {
208
212
if path. qualifier ( ) . is_some ( ) {
209
213
return None ;
@@ -220,9 +224,7 @@ impl<'a> Ctx<'a> {
220
224
221
225
match resolution {
222
226
hir:: PathResolution :: TypeParam ( tp) => {
223
- if let Some ( TypeOrConstSubst { subst, .. } ) =
224
- self . type_and_const_substs . get ( & tp. merge ( ) )
225
- {
227
+ if let Some ( subst) = self . type_substs . get ( & tp) {
226
228
let parent = path. syntax ( ) . parent ( ) ?;
227
229
if let Some ( parent) = ast:: Path :: cast ( parent. clone ( ) ) {
228
230
// Path inside path means that there is an associated
@@ -290,10 +292,8 @@ impl<'a> Ctx<'a> {
290
292
ted:: replace ( path. syntax ( ) , res. syntax ( ) )
291
293
}
292
294
hir:: PathResolution :: ConstParam ( cp) => {
293
- if let Some ( TypeOrConstSubst { subst, .. } ) =
294
- self . type_and_const_substs . get ( & cp. merge ( ) )
295
- {
296
- ted:: replace ( path. syntax ( ) , subst. clone_subtree ( ) . clone_for_update ( ) . syntax ( ) ) ;
295
+ if let Some ( subst) = self . const_substs . get ( & cp) {
296
+ ted:: replace ( path. syntax ( ) , subst. clone_subtree ( ) . clone_for_update ( ) ) ;
297
297
}
298
298
}
299
299
hir:: PathResolution :: Local ( _)
0 commit comments