@@ -17,11 +17,6 @@ struct AstSubsts {
1717 lifetimes : Vec < ast:: LifetimeArg > ,
1818}
1919
20- struct TypeOrConstSubst {
21- subst : ast:: Type ,
22- to_be_transformed : bool ,
23- }
24-
2520type LifetimeName = String ;
2621
2722/// `PathTransform` substitutes path in SyntaxNodes in bulk.
@@ -115,8 +110,10 @@ impl<'a> PathTransform<'a> {
115110 Some ( hir:: GenericDef :: Trait ( _) ) => 1 ,
116111 _ => 0 ,
117112 } ;
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
120117 . into_iter ( )
121118 . flat_map ( |it| it. type_params ( db) )
122119 . skip ( skip)
@@ -127,50 +124,57 @@ impl<'a> PathTransform<'a> {
127124 // a default type. If they do, go for that type from `hir` to `ast` so
128125 // the resulting change can be applied correctly.
129126 . 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+ }
135132 }
136133 ( 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+ }
146142 }
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+ } ) ;
150150 let lifetime_substs: FxHashMap < _ , _ > = self
151151 . generic_def
152152 . into_iter ( )
153153 . flat_map ( |it| it. lifetime_params ( db) )
154154 . zip ( self . substs . lifetimes . clone ( ) )
155155 . filter_map ( |( k, v) | Some ( ( k. name ( db) . display ( db. upcast ( ) ) . to_string ( ) , v. lifetime ( ) ?) ) )
156156 . collect ( ) ;
157- Ctx {
158- type_and_const_substs,
157+ let ctx = Ctx {
158+ type_substs,
159+ const_substs,
159160 lifetime_substs,
160161 target_module,
161162 source_scope : self . source_scope ,
162- }
163+ } ;
164+ ctx. transform_default_type_substs ( default_types) ;
165+ ctx
163166 }
164167}
165168
166169struct 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 > ,
168172 lifetime_substs : FxHashMap < LifetimeName , ast:: Lifetime > ,
169173 target_module : hir:: Module ,
170174 source_scope : & ' a SemanticsScope < ' a > ,
171175}
172176
173- fn preorder ( item : & SyntaxNode ) -> impl Iterator < Item = SyntaxNode > {
177+ fn postorder ( item : & SyntaxNode ) -> impl Iterator < Item = SyntaxNode > {
174178 item. preorder ( ) . filter_map ( |event| match event {
175179 syntax:: WalkEvent :: Enter ( _) => None ,
176180 syntax:: WalkEvent :: Leave ( node) => Some ( node) ,
@@ -179,31 +183,31 @@ fn preorder(item: &SyntaxNode) -> impl Iterator<Item = SyntaxNode> {
179183
180184impl < ' a > Ctx < ' a > {
181185 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-
192186 // `transform_path` may update a node's parent and that would break the
193187 // tree traversal. Thus all paths in the tree are collected into a vec
194188 // 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 < _ > > ( ) ;
196190 for path in paths {
197191 self . transform_path ( path) ;
198192 }
199193
200- preorder ( item) . filter_map ( ast:: Lifetime :: cast) . for_each ( |lifetime| {
194+ postorder ( item) . filter_map ( ast:: Lifetime :: cast) . for_each ( |lifetime| {
201195 if let Some ( subst) = self . lifetime_substs . get ( & lifetime. syntax ( ) . text ( ) . to_string ( ) ) {
202196 ted:: replace ( lifetime. syntax ( ) , subst. clone_subtree ( ) . clone_for_update ( ) . syntax ( ) ) ;
203197 }
204198 } ) ;
205199 }
206200
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+
207211 fn transform_path ( & self , path : ast:: Path ) -> Option < ( ) > {
208212 if path. qualifier ( ) . is_some ( ) {
209213 return None ;
@@ -220,9 +224,7 @@ impl<'a> Ctx<'a> {
220224
221225 match resolution {
222226 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) {
226228 let parent = path. syntax ( ) . parent ( ) ?;
227229 if let Some ( parent) = ast:: Path :: cast ( parent. clone ( ) ) {
228230 // Path inside path means that there is an associated
@@ -290,10 +292,8 @@ impl<'a> Ctx<'a> {
290292 ted:: replace ( path. syntax ( ) , res. syntax ( ) )
291293 }
292294 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 ( ) ) ;
297297 }
298298 }
299299 hir:: PathResolution :: Local ( _)
0 commit comments