@@ -46,11 +46,19 @@ pub(crate) fn inline_type_alias(acc: &mut Assists, ctx: &AssistContext) -> Optio
4646 let concrete_type = alias. ty ( ) ?;
4747
4848 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) ?,
5260 & concrete_type,
53- ) ?
61+ )
5462 } else {
5563 concrete_type. to_string ( )
5664 } ;
@@ -67,6 +75,83 @@ pub(crate) fn inline_type_alias(acc: &mut Assists, ctx: &AssistContext) -> Optio
6775 )
6876}
6977
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+
70155/// This doesn't attempt to ensure specified generics are compatible with those
71156/// required by the type alias, other than lifetimes which must either all be
72157/// 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
94179/// 3. Remove wildcard lifetimes entirely:
95180///
96181/// &[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 ,
100185 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 {
156187 let updated_concrete_type = concrete_type. clone_for_update ( ) ;
157188 let mut replacements = Vec :: new ( ) ;
158189 let mut removals = Vec :: new ( ) ;
@@ -161,20 +192,21 @@ fn get_replacement_for_generic_alias(
161192 let syntax_string = syntax. to_string ( ) ;
162193 let syntax_str = syntax_string. as_str ( ) ;
163194
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+ }
168203
169- if let Some ( ws) = syntax. next_sibling_or_token ( ) {
170- removals. push ( ws. clone ( ) ) ;
204+ continue ;
171205 }
172206
173- continue ;
207+ replacements . push ( ( syntax . clone ( ) , new_lifetime . syntax ( ) . clone_for_update ( ) ) ) ;
174208 }
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) {
178210 let new_string = replacement_syntax. to_string ( ) ;
179211 let new = if new_string == "_" {
180212 make:: wildcard_pat ( ) . syntax ( ) . clone_for_update ( )
@@ -194,7 +226,7 @@ fn get_replacement_for_generic_alias(
194226 ted:: remove ( syntax) ;
195227 }
196228
197- Some ( updated_concrete_type. to_string ( ) )
229+ updated_concrete_type. to_string ( )
198230}
199231
200232fn 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
205237 // keep the order, so we must get the `ast::TypeAlias` from the hir
206238 // definition.
207239 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 )
209241 } else {
210242 None
211243 }
212244}
213245
214- enum OtherGeneric {
246+ enum ConstOrTypeGeneric {
215247 ConstArg ( ast:: ConstArg ) ,
216248 TypeArg ( ast:: TypeArg ) ,
217249 ConstParam ( ast:: ConstParam ) ,
218250 TypeParam ( ast:: TypeParam ) ,
219251}
220252
221- impl OtherGeneric {
222- fn replacement_key ( & self ) -> String {
253+ impl ConstOrTypeGeneric {
254+ fn replacement_key ( & self ) -> Option < String > {
223255 // Only params are used as replacement keys.
224256 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 ,
229260 }
230261 }
231262
232263 fn replacement_value ( & self ) -> Option < SyntaxNode > {
233264 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 ( ) ,
238269 } )
239270 }
240271}
241272
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 > {
243276 let mut others = Vec :: new ( ) ;
244277
245278 for param in generics. generic_params ( ) {
246279 match param {
247280 ast:: GenericParam :: LifetimeParam ( _) => { }
248281 ast:: GenericParam :: ConstParam ( cp) => {
249- others. push ( OtherGeneric :: ConstParam ( cp) ) ;
282+ others. push ( ConstOrTypeGeneric :: ConstParam ( cp) ) ;
250283 }
251- ast:: GenericParam :: TypeParam ( tp) => others. push ( OtherGeneric :: TypeParam ( tp) ) ,
284+ ast:: GenericParam :: TypeParam ( tp) => others. push ( ConstOrTypeGeneric :: TypeParam ( tp) ) ,
252285 }
253286 }
254287
255288 others
256289}
257290
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 > {
259294 let mut others = Vec :: new ( ) ;
260295
261296 // 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<
264299 for arg in generics. generic_args ( ) {
265300 match arg {
266301 ast:: GenericArg :: TypeArg ( ta) => {
267- others. push ( OtherGeneric :: TypeArg ( ta) ) ;
302+ others. push ( ConstOrTypeGeneric :: TypeArg ( ta) ) ;
268303 }
269304 ast:: GenericArg :: ConstArg ( ca) => {
270- others. push ( OtherGeneric :: ConstArg ( ca) ) ;
305+ others. push ( ConstOrTypeGeneric :: ConstArg ( ca) ) ;
271306 }
272307 _ => { }
273308 }
0 commit comments