@@ -46,11 +46,19 @@ pub(crate) fn inline_type_alias(acc: &mut Assists, ctx: &AssistContext) -> Optio
46
46
let concrete_type = alias. ty ( ) ?;
47
47
48
48
let replacement = if let Some ( alias_generics) = alias. generic_param_list ( ) {
49
- get_replacement_for_generic_alias (
50
- alias_instance. syntax ( ) . descendants ( ) . find_map ( ast:: GenericArgList :: cast) ,
51
- alias_generics,
49
+ if alias_generics. generic_params ( ) . next ( ) . is_none ( ) {
50
+ cov_mark:: hit!( no_generics_params) ;
51
+ return None ;
52
+ }
53
+
54
+ let instance_args =
55
+ alias_instance. syntax ( ) . descendants ( ) . find_map ( ast:: GenericArgList :: cast) ;
56
+
57
+ create_replacement (
58
+ & LifetimeMap :: new ( & instance_args, & alias_generics) ?,
59
+ & ConstAndTypeMap :: new ( & instance_args, & alias_generics) ?,
52
60
& concrete_type,
53
- ) ?
61
+ )
54
62
} else {
55
63
concrete_type. to_string ( )
56
64
} ;
@@ -67,6 +75,83 @@ pub(crate) fn inline_type_alias(acc: &mut Assists, ctx: &AssistContext) -> Optio
67
75
)
68
76
}
69
77
78
+ struct LifetimeMap ( HashMap < String , ast:: Lifetime > ) ;
79
+
80
+ impl LifetimeMap {
81
+ fn new (
82
+ instance_args : & Option < ast:: GenericArgList > ,
83
+ alias_generics : & ast:: GenericParamList ,
84
+ ) -> Option < Self > {
85
+ let mut inner = HashMap :: new ( ) ;
86
+
87
+ let wildcard_lifetime = make:: lifetime ( "'_" ) ;
88
+ let lifetimes = alias_generics
89
+ . lifetime_params ( )
90
+ . filter_map ( |lp| lp. lifetime ( ) )
91
+ . map ( |l| l. to_string ( ) )
92
+ . collect_vec ( ) ;
93
+
94
+ for lifetime in & lifetimes {
95
+ inner. insert ( lifetime. to_string ( ) , wildcard_lifetime. clone ( ) ) ;
96
+ }
97
+
98
+ if let Some ( instance_generic_args_list) = & instance_args {
99
+ for ( index, lifetime) in instance_generic_args_list
100
+ . lifetime_args ( )
101
+ . filter_map ( |arg| arg. lifetime ( ) )
102
+ . enumerate ( )
103
+ {
104
+ let key = match lifetimes. get ( index) {
105
+ Some ( key) => key,
106
+ None => {
107
+ cov_mark:: hit!( too_many_lifetimes) ;
108
+ return None ;
109
+ }
110
+ } ;
111
+
112
+ inner. insert ( key. clone ( ) , lifetime) ;
113
+ }
114
+ }
115
+
116
+ Some ( Self ( inner) )
117
+ }
118
+ }
119
+
120
+ struct ConstAndTypeMap ( HashMap < String , SyntaxNode > ) ;
121
+
122
+ impl ConstAndTypeMap {
123
+ fn new (
124
+ instance_args : & Option < ast:: GenericArgList > ,
125
+ alias_generics : & ast:: GenericParamList ,
126
+ ) -> Option < Self > {
127
+ let mut inner = HashMap :: new ( ) ;
128
+ let instance_generics = generic_args_to_const_and_type_generics ( instance_args) ;
129
+ let alias_generics = generic_param_list_to_const_and_type_generics ( & alias_generics) ;
130
+
131
+ if instance_generics. len ( ) > alias_generics. len ( ) {
132
+ cov_mark:: hit!( too_many_generic_args) ;
133
+ return None ;
134
+ }
135
+
136
+ // Any declaration generics that don't have a default value must have one
137
+ // provided by the instance.
138
+ for ( i, declaration_generic) in alias_generics. iter ( ) . enumerate ( ) {
139
+ let key = declaration_generic. replacement_key ( ) ?;
140
+
141
+ if let Some ( instance_generic) = instance_generics. get ( i) {
142
+ inner. insert ( key, instance_generic. replacement_value ( ) ?) ;
143
+ } else if let Some ( value) = declaration_generic. replacement_value ( ) {
144
+ inner. insert ( key, value) ;
145
+ } else {
146
+ cov_mark:: hit!( missing_replacement_param) ;
147
+ return None ;
148
+ }
149
+ }
150
+
151
+ Some ( Self ( inner) )
152
+ }
153
+ }
154
+
70
155
/// This doesn't attempt to ensure specified generics are compatible with those
71
156
/// required by the type alias, other than lifetimes which must either all be
72
157
/// specified or all omitted. It will replace TypeArgs with ConstArgs and vice
@@ -94,65 +179,11 @@ pub(crate) fn inline_type_alias(acc: &mut Assists, ctx: &AssistContext) -> Optio
94
179
/// 3. Remove wildcard lifetimes entirely:
95
180
///
96
181
/// &[u64; 100]
97
- fn get_replacement_for_generic_alias (
98
- instance_generic_args_list : Option < ast :: GenericArgList > ,
99
- alias_generics : ast :: GenericParamList ,
182
+ fn create_replacement (
183
+ lifetime_map : & LifetimeMap ,
184
+ const_and_type_map : & ConstAndTypeMap ,
100
185
concrete_type : & ast:: Type ,
101
- ) -> Option < String > {
102
- if alias_generics. generic_params ( ) . count ( ) == 0 {
103
- cov_mark:: hit!( no_generics_params) ;
104
- return None ;
105
- }
106
-
107
- let mut lifetime_mappings = HashMap :: < & str , ast:: Lifetime > :: new ( ) ;
108
- let mut other_mappings = HashMap :: < String , SyntaxNode > :: new ( ) ;
109
-
110
- let wildcard_lifetime = make:: lifetime ( "'_" ) ;
111
- let alias_lifetimes = alias_generics. lifetime_params ( ) . map ( |l| l. to_string ( ) ) . collect_vec ( ) ;
112
- for lifetime in & alias_lifetimes {
113
- lifetime_mappings. insert ( lifetime, wildcard_lifetime. clone ( ) ) ;
114
- }
115
-
116
- if let Some ( ref instance_generic_args_list) = instance_generic_args_list {
117
- for ( index, lifetime) in instance_generic_args_list
118
- . lifetime_args ( )
119
- . map ( |arg| arg. lifetime ( ) . expect ( "LifetimeArg has a Lifetime" ) )
120
- . enumerate ( )
121
- {
122
- if index >= alias_lifetimes. len ( ) {
123
- cov_mark:: hit!( too_many_lifetimes) ;
124
- return None ;
125
- }
126
-
127
- let key = & alias_lifetimes[ index] ;
128
-
129
- lifetime_mappings. insert ( key, lifetime) ;
130
- }
131
- }
132
-
133
- let instance_generics = generic_args_to_other_generics ( instance_generic_args_list) ;
134
- let alias_generics = generic_param_list_to_other_generics ( & alias_generics) ;
135
-
136
- if instance_generics. len ( ) > alias_generics. len ( ) {
137
- cov_mark:: hit!( too_many_generic_args) ;
138
- return None ;
139
- }
140
-
141
- // Any declaration generics that don't have a default value must have one
142
- // provided by the instance.
143
- for ( i, declaration_generic) in alias_generics. iter ( ) . enumerate ( ) {
144
- let key = declaration_generic. replacement_key ( ) ;
145
-
146
- if let Some ( instance_generic) = instance_generics. get ( i) {
147
- other_mappings. insert ( key, instance_generic. replacement_value ( ) ?) ;
148
- } else if let Some ( value) = declaration_generic. replacement_value ( ) {
149
- other_mappings. insert ( key, value) ;
150
- } else {
151
- cov_mark:: hit!( missing_replacement_param) ;
152
- return None ;
153
- }
154
- }
155
-
186
+ ) -> String {
156
187
let updated_concrete_type = concrete_type. clone_for_update ( ) ;
157
188
let mut replacements = Vec :: new ( ) ;
158
189
let mut removals = Vec :: new ( ) ;
@@ -161,20 +192,21 @@ fn get_replacement_for_generic_alias(
161
192
let syntax_string = syntax. to_string ( ) ;
162
193
let syntax_str = syntax_string. as_str ( ) ;
163
194
164
- if syntax. kind ( ) == SyntaxKind :: LIFETIME {
165
- let new = lifetime_mappings. get ( syntax_str) . expect ( "lifetime is mapped" ) ;
166
- if new. text ( ) == "'_" {
167
- removals. push ( NodeOrToken :: Node ( syntax. clone ( ) ) ) ;
195
+ if let Some ( old_lifetime) = ast:: Lifetime :: cast ( syntax. clone ( ) ) {
196
+ if let Some ( new_lifetime) = lifetime_map. 0 . get ( & old_lifetime. to_string ( ) ) {
197
+ if new_lifetime. text ( ) == "'_" {
198
+ removals. push ( NodeOrToken :: Node ( syntax. clone ( ) ) ) ;
199
+
200
+ if let Some ( ws) = syntax. next_sibling_or_token ( ) {
201
+ removals. push ( ws. clone ( ) ) ;
202
+ }
168
203
169
- if let Some ( ws) = syntax. next_sibling_or_token ( ) {
170
- removals. push ( ws. clone ( ) ) ;
204
+ continue ;
171
205
}
172
206
173
- continue ;
207
+ replacements . push ( ( syntax . clone ( ) , new_lifetime . syntax ( ) . clone_for_update ( ) ) ) ;
174
208
}
175
-
176
- replacements. push ( ( syntax. clone ( ) , new. syntax ( ) . clone_for_update ( ) ) ) ;
177
- } else if let Some ( replacement_syntax) = other_mappings. get ( syntax_str) {
209
+ } else if let Some ( replacement_syntax) = const_and_type_map. 0 . get ( syntax_str) {
178
210
let new_string = replacement_syntax. to_string ( ) ;
179
211
let new = if new_string == "_" {
180
212
make:: wildcard_pat ( ) . syntax ( ) . clone_for_update ( )
@@ -194,7 +226,7 @@ fn get_replacement_for_generic_alias(
194
226
ted:: remove ( syntax) ;
195
227
}
196
228
197
- Some ( updated_concrete_type. to_string ( ) )
229
+ updated_concrete_type. to_string ( )
198
230
}
199
231
200
232
fn get_type_alias ( ctx : & AssistContext , path : & ast:: PathType ) -> Option < ast:: TypeAlias > {
@@ -205,57 +237,60 @@ fn get_type_alias(ctx: &AssistContext, path: &ast::PathType) -> Option<ast::Type
205
237
// keep the order, so we must get the `ast::TypeAlias` from the hir
206
238
// definition.
207
239
if let PathResolution :: Def ( hir:: ModuleDef :: TypeAlias ( ta) ) = resolved_path {
208
- ast :: TypeAlias :: cast ( ctx. sema . source ( ta) ?. syntax ( ) . value . clone ( ) )
240
+ Some ( ctx. sema . source ( ta) ?. value )
209
241
} else {
210
242
None
211
243
}
212
244
}
213
245
214
- enum OtherGeneric {
246
+ enum ConstOrTypeGeneric {
215
247
ConstArg ( ast:: ConstArg ) ,
216
248
TypeArg ( ast:: TypeArg ) ,
217
249
ConstParam ( ast:: ConstParam ) ,
218
250
TypeParam ( ast:: TypeParam ) ,
219
251
}
220
252
221
- impl OtherGeneric {
222
- fn replacement_key ( & self ) -> String {
253
+ impl ConstOrTypeGeneric {
254
+ fn replacement_key ( & self ) -> Option < String > {
223
255
// Only params are used as replacement keys.
224
256
match self {
225
- OtherGeneric :: ConstArg ( _) => unreachable ! ( ) ,
226
- OtherGeneric :: TypeArg ( _) => unreachable ! ( ) ,
227
- OtherGeneric :: ConstParam ( cp) => cp. name ( ) . expect ( "ConstParam has a name" ) . to_string ( ) ,
228
- OtherGeneric :: TypeParam ( tp) => tp. name ( ) . expect ( "TypeParam has a name" ) . to_string ( ) ,
257
+ ConstOrTypeGeneric :: ConstParam ( cp) => Some ( cp. name ( ) ?. to_string ( ) ) ,
258
+ ConstOrTypeGeneric :: TypeParam ( tp) => Some ( tp. name ( ) ?. to_string ( ) ) ,
259
+ _ => None ,
229
260
}
230
261
}
231
262
232
263
fn replacement_value ( & self ) -> Option < SyntaxNode > {
233
264
Some ( match self {
234
- OtherGeneric :: ConstArg ( ca) => ca. expr ( ) ?. syntax ( ) . clone ( ) ,
235
- OtherGeneric :: TypeArg ( ta) => ta. syntax ( ) . clone ( ) ,
236
- OtherGeneric :: ConstParam ( cp) => cp. default_val ( ) ?. syntax ( ) . clone ( ) ,
237
- OtherGeneric :: TypeParam ( tp) => tp. default_type ( ) ?. syntax ( ) . clone ( ) ,
265
+ ConstOrTypeGeneric :: ConstArg ( ca) => ca. expr ( ) ?. syntax ( ) . clone ( ) ,
266
+ ConstOrTypeGeneric :: TypeArg ( ta) => ta. syntax ( ) . clone ( ) ,
267
+ ConstOrTypeGeneric :: ConstParam ( cp) => cp. default_val ( ) ?. syntax ( ) . clone ( ) ,
268
+ ConstOrTypeGeneric :: TypeParam ( tp) => tp. default_type ( ) ?. syntax ( ) . clone ( ) ,
238
269
} )
239
270
}
240
271
}
241
272
242
- fn generic_param_list_to_other_generics ( generics : & ast:: GenericParamList ) -> Vec < OtherGeneric > {
273
+ fn generic_param_list_to_const_and_type_generics (
274
+ generics : & ast:: GenericParamList ,
275
+ ) -> Vec < ConstOrTypeGeneric > {
243
276
let mut others = Vec :: new ( ) ;
244
277
245
278
for param in generics. generic_params ( ) {
246
279
match param {
247
280
ast:: GenericParam :: LifetimeParam ( _) => { }
248
281
ast:: GenericParam :: ConstParam ( cp) => {
249
- others. push ( OtherGeneric :: ConstParam ( cp) ) ;
282
+ others. push ( ConstOrTypeGeneric :: ConstParam ( cp) ) ;
250
283
}
251
- ast:: GenericParam :: TypeParam ( tp) => others. push ( OtherGeneric :: TypeParam ( tp) ) ,
284
+ ast:: GenericParam :: TypeParam ( tp) => others. push ( ConstOrTypeGeneric :: TypeParam ( tp) ) ,
252
285
}
253
286
}
254
287
255
288
others
256
289
}
257
290
258
- fn generic_args_to_other_generics ( generics : Option < ast:: GenericArgList > ) -> Vec < OtherGeneric > {
291
+ fn generic_args_to_const_and_type_generics (
292
+ generics : & Option < ast:: GenericArgList > ,
293
+ ) -> Vec < ConstOrTypeGeneric > {
259
294
let mut others = Vec :: new ( ) ;
260
295
261
296
// It's fine for there to be no instance generics because the declaration
@@ -264,10 +299,10 @@ fn generic_args_to_other_generics(generics: Option<ast::GenericArgList>) -> Vec<
264
299
for arg in generics. generic_args ( ) {
265
300
match arg {
266
301
ast:: GenericArg :: TypeArg ( ta) => {
267
- others. push ( OtherGeneric :: TypeArg ( ta) ) ;
302
+ others. push ( ConstOrTypeGeneric :: TypeArg ( ta) ) ;
268
303
}
269
304
ast:: GenericArg :: ConstArg ( ca) => {
270
- others. push ( OtherGeneric :: ConstArg ( ca) ) ;
305
+ others. push ( ConstOrTypeGeneric :: ConstArg ( ca) ) ;
271
306
}
272
307
_ => { }
273
308
}
0 commit comments