@@ -5,23 +5,27 @@ use std::{iter, sync::Arc};
5
5
use base_db:: impl_intern_key_ref;
6
6
use chalk_ir:: {
7
7
BoundVar , DebruijnIndex ,
8
+ cast:: Cast ,
8
9
fold:: { TypeFoldable , TypeFolder , TypeSuperFoldable } ,
9
10
} ;
10
11
use chalk_solve:: rust_ir:: AssociatedTyValueBound ;
11
12
use hir_def:: {
12
- AssocItemId , FunctionId , GenericDefId , ImplId , TraitId ,
13
+ AssocItemId , FunctionId , GenericDefId , GenericParamId , ImplId , TraitId ,
13
14
hir:: generics:: { GenericParams , TypeOrConstParamData } ,
15
+ resolver:: HasResolver ,
14
16
} ;
15
17
use rustc_hash:: FxHashMap ;
18
+ use thin_vec:: ThinVec ;
16
19
17
20
use crate :: {
18
21
AliasTy , AnyTraitAssocType , Binders , Const , ConstData , ConstValue , DomainGoal , Goal , GoalData ,
19
- InferenceTable , Interner , Lifetime , LifetimeData , PlaceholderIndex , ProjectionTy , Substitution ,
20
- Ty , TyKind , VariableKinds ,
22
+ ImplTraitLoweringMode , InferenceTable , Interner , Lifetime , LifetimeData , LifetimeElisionKind ,
23
+ ParamLoweringMode , PlaceholderIndex , ProjectionTy , Substitution , TraitRef , Ty , TyKind ,
24
+ TyLoweringContext , VariableKinds ,
21
25
chalk_db:: { AssociatedTyValue , inline_bound_to_generic_predicate} ,
22
26
db:: HirDatabase ,
23
27
from_assoc_type_id, from_placeholder_idx,
24
- generics:: generics,
28
+ generics:: { Generics , generics} ,
25
29
lt_from_placeholder_idx,
26
30
mapping:: { ToChalk , to_assoc_type_id_rpitit} ,
27
31
variable_kinds_from_generics,
@@ -58,15 +62,14 @@ impl_intern_key_ref!(RpititImplAssocTyId, RpititImplAssocTy);
58
62
#[ salsa_macros:: tracked( return_ref) ]
59
63
pub ( crate ) fn impl_method_rpitit_values (
60
64
db : & dyn HirDatabase ,
61
- impl_id : hir_def :: ImplId ,
65
+ impl_id : ImplId ,
62
66
trait_method_id : FunctionId ,
63
67
) -> Box < [ Arc < AssociatedTyValue > ] > {
64
68
let impl_items = db. impl_items ( impl_id) ;
65
69
let trait_method_generics = generics ( db, trait_method_id. into ( ) ) ;
66
- let impl_datum =
67
- db. impl_datum ( impl_id. loc ( db) . container . krate ( ) , hir_def:: ImplId :: to_chalk ( impl_id, db) ) ;
68
70
let trait_method = db. function_signature ( trait_method_id) ;
69
- let Some ( impl_method) = impl_items. items . iter ( ) . find_map ( |( name, id) | {
71
+ let impl_trait_ref = db. impl_trait ( impl_id) . expect ( "invalid impl passed to Chalk" ) ;
72
+ let impl_method = impl_items. items . iter ( ) . find_map ( |( name, id) | {
70
73
if * name == trait_method. name {
71
74
match * id {
72
75
AssocItemId :: FunctionId ( it) => Some ( it) ,
@@ -75,9 +78,19 @@ pub(crate) fn impl_method_rpitit_values(
75
78
} else {
76
79
None
77
80
}
78
- } ) else {
79
- // FIXME: Handle defaulted methods.
80
- return Box :: default ( ) ;
81
+ } ) ;
82
+ let impl_method = match impl_method {
83
+ Some ( impl_method) => impl_method,
84
+ None => {
85
+ // Method not in the impl, so it is defaulted.
86
+ return defaulted_impl_method_rpitit_values (
87
+ db,
88
+ impl_id,
89
+ trait_method_id,
90
+ impl_trait_ref,
91
+ & trait_method_generics,
92
+ ) ;
93
+ }
81
94
} ;
82
95
83
96
let impl_method_generics = generics ( db, impl_method. into ( ) ) ;
@@ -107,11 +120,7 @@ pub(crate) fn impl_method_rpitit_values(
107
120
let trait_ref_placeholder_subst =
108
121
& impl_method_placeholder_subst. as_slice ( Interner ) [ ..impl_method_generics. len_parent ( ) ] ;
109
122
// We want to substitute the TraitRef with placeholders, but placeholders from the method, not the impl.
110
- let impl_trait_ref = impl_datum
111
- . binders
112
- . as_ref ( )
113
- . map ( |it| it. trait_ref . clone ( ) )
114
- . substitute ( Interner , trait_ref_placeholder_subst) ;
123
+ let impl_trait_ref = impl_trait_ref. substitute ( Interner , trait_ref_placeholder_subst) ;
115
124
let trait_to_impl_args = Substitution :: from_iter (
116
125
Interner ,
117
126
impl_trait_ref. substitution . as_slice ( Interner ) . iter ( ) . chain (
@@ -139,7 +148,7 @@ pub(crate) fn impl_method_rpitit_values(
139
148
table. unify ( & trait_method_ret, & impl_method_ret) ;
140
149
table. resolve_obligations_as_possible ( ) ;
141
150
142
- return trait_rpitit_to_infer_var
151
+ trait_rpitit_to_infer_var
143
152
. into_iter ( )
144
153
. map ( |( trait_assoc_id, infer_var) | {
145
154
let impl_rpitit = table. resolve_completely ( infer_var) ;
@@ -148,6 +157,11 @@ pub(crate) fn impl_method_rpitit_values(
148
157
db,
149
158
method : impl_method. into ( ) ,
150
159
method_generics : impl_method_generics. self_params ( ) ,
160
+ parent : impl_id. into ( ) ,
161
+ parent_generics : impl_method_generics
162
+ . parent_generics ( )
163
+ . expect ( "parent should be an impl" )
164
+ . self_params ( ) ,
151
165
} ,
152
166
DebruijnIndex :: INNERMOST ,
153
167
) ;
@@ -169,146 +183,142 @@ pub(crate) fn impl_method_rpitit_values(
169
183
value : impl_rpitit,
170
184
} )
171
185
} )
172
- . collect ( ) ;
173
-
174
- #[ derive( chalk_derive:: FallibleTypeFolder ) ]
175
- #[ has_interner( Interner ) ]
176
- struct RpititToInferVarFolder < ' a , ' b > {
177
- db : & ' a dyn HirDatabase ,
178
- table : & ' a mut InferenceTable < ' b > ,
179
- trait_rpitit_to_infer_var : FxHashMap < RpititTraitAssocTyId , Ty > ,
180
- trait_method_id : FunctionId ,
181
- }
182
- impl TypeFolder < Interner > for RpititToInferVarFolder < ' _ , ' _ > {
183
- fn as_dyn ( & mut self ) -> & mut dyn TypeFolder < Interner > {
184
- self
185
- }
186
-
187
- fn interner ( & self ) -> Interner {
188
- Interner
189
- }
186
+ . collect ( )
187
+ }
190
188
191
- fn fold_ty ( & mut self , ty : Ty , outer_binder : DebruijnIndex ) -> Ty {
192
- let result = match ty. kind ( Interner ) {
193
- TyKind :: Alias ( AliasTy :: Projection ( ProjectionTy {
194
- associated_ty_id,
195
- substitution,
196
- } ) )
197
- | TyKind :: AssociatedType ( associated_ty_id, substitution) => {
198
- if let AnyTraitAssocType :: Rpitit ( assoc_id) =
199
- from_assoc_type_id ( self . db , * associated_ty_id)
200
- {
201
- let assoc = assoc_id. loc ( self . db ) ;
202
- if assoc. synthesized_from_method == self . trait_method_id {
203
- if let Some ( ty) = self . trait_rpitit_to_infer_var . get ( & assoc_id) {
204
- return ty. clone ( ) ;
205
- }
206
-
207
- // Replace with new infer var.
208
- // This needs to come before we fold the bounds, because they also contain this associated type.
209
- let var = self . table . new_type_var ( ) ;
210
- self . trait_rpitit_to_infer_var . insert ( assoc_id, var. clone ( ) ) ;
211
-
212
- // Recurse into bounds, so that nested RPITITs will be handled correctly.
213
- for bound in assoc. bounds . clone ( ) . substitute ( Interner , substitution) {
214
- let bound = inline_bound_to_generic_predicate ( & bound, var. clone ( ) ) ;
215
- let bound = bound. fold_with ( self , outer_binder) ;
216
- let bound = self . table . normalize_associated_types_in ( bound) ;
217
- self . table . register_obligation ( Goal :: new (
218
- Interner ,
219
- GoalData :: Quantified (
220
- chalk_ir:: QuantifierKind :: ForAll ,
221
- bound. map ( |bound| {
222
- Goal :: new (
223
- Interner ,
224
- GoalData :: DomainGoal ( DomainGoal :: Holds ( bound) ) ,
225
- )
226
- } ) ,
227
- ) ,
228
- ) ) ;
229
- }
230
-
231
- return var;
232
- }
233
- }
234
- ty. clone ( )
235
- }
236
- _ => ty. clone ( ) ,
237
- } ;
238
- result. super_fold_with ( self , outer_binder)
239
- }
240
- }
189
+ fn defaulted_impl_method_rpitit_values (
190
+ db : & dyn HirDatabase ,
191
+ impl_id : ImplId ,
192
+ trait_method_id : FunctionId ,
193
+ impl_trait_ref : Binders < TraitRef > ,
194
+ trait_method_generics : & Generics ,
195
+ ) -> Box < [ Arc < AssociatedTyValue > ] > {
196
+ let defaulted_rpitit_values = defaulted_trait_method_rpitit_values ( db, trait_method_id) ;
197
+ let impl_generics = generics ( db, impl_id. into ( ) ) ;
198
+ // The associated type generics as the same as the trait method's, but we take the impl as
199
+ // the parent instead of the trait.
200
+ // The impl generics need to be shifted to account for the associated type generics.
201
+ let trait_method_subst = trait_method_generics. bound_vars_subst ( db, DebruijnIndex :: INNERMOST ) ;
202
+ let impl_subst = Substitution :: from_iter (
203
+ Interner ,
204
+ impl_generics. iter_id ( ) . enumerate ( ) . map ( |( idx, id) | match id {
205
+ GenericParamId :: ConstParamId ( id) => {
206
+ BoundVar :: new ( DebruijnIndex :: INNERMOST , idx + trait_method_generics. len_self ( ) )
207
+ . to_const ( Interner , db. const_param_ty ( id) )
208
+ . cast ( Interner )
209
+ }
210
+ GenericParamId :: TypeParamId ( _) => {
211
+ BoundVar :: new ( DebruijnIndex :: INNERMOST , idx + trait_method_generics. len_self ( ) )
212
+ . to_ty ( Interner )
213
+ . cast ( Interner )
214
+ }
215
+ GenericParamId :: LifetimeParamId ( _) => {
216
+ BoundVar :: new ( DebruijnIndex :: INNERMOST , idx + trait_method_generics. len_self ( ) )
217
+ . to_lifetime ( Interner )
218
+ . cast ( Interner )
219
+ }
220
+ } ) ,
221
+ ) ;
222
+ let impl_trait_ref = impl_trait_ref. substitute ( Interner , & impl_subst) ;
223
+ let impl_rpitit_subst = Substitution :: from_iter (
224
+ Interner ,
225
+ trait_method_subst. as_slice ( Interner ) [ ..trait_method_generics. len_self ( ) ]
226
+ . iter ( )
227
+ . chain ( impl_trait_ref. substitution . as_slice ( Interner ) ) ,
228
+ ) ;
229
+ let binders = VariableKinds :: from_iter (
230
+ Interner ,
231
+ variable_kinds_from_generics (
232
+ db,
233
+ trait_method_generics. iter_self_id ( ) . chain ( impl_generics. iter_id ( ) ) ,
234
+ ) ,
235
+ ) ;
236
+ defaulted_rpitit_values
237
+ . iter ( )
238
+ . map ( |( trait_assoc, trait_rpitit) | {
239
+ let impl_rpitit = trait_rpitit. clone ( ) . substitute ( Interner , & impl_rpitit_subst) ;
240
+ Arc :: new ( AssociatedTyValue {
241
+ associated_ty_id : to_assoc_type_id_rpitit ( * trait_assoc) ,
242
+ impl_id : ImplId :: to_chalk ( impl_id, db) ,
243
+ value : Binders :: new ( binders. clone ( ) , AssociatedTyValueBound { ty : impl_rpitit } ) ,
244
+ } )
245
+ } )
246
+ . collect ( )
247
+ }
241
248
242
- # [ derive ( chalk_derive :: FallibleTypeFolder ) ]
243
- # [ has_interner ( Interner ) ]
244
- struct PlaceholderToBoundVarFolder < ' a > {
245
- db : & ' a dyn HirDatabase ,
246
- method : GenericDefId ,
247
- method_generics : & ' a GenericParams ,
248
- }
249
- impl TypeFolder < Interner > for PlaceholderToBoundVarFolder < ' _ > {
250
- fn as_dyn ( & mut self ) -> & mut dyn TypeFolder < Interner > {
251
- self
252
- }
249
+ /// This is called only for defaulted trait methods, as there the value of the RPITIT associated
250
+ /// items on an impl (if the method body is left defaulted) is the same as with the trait method.
251
+ // This returns an `EmptyOptimizedThinVec` and not `Box<[]>` because this is called from inference,
252
+ // and most methods don't have RPITITs.
253
+ # [ salsa_macros :: tracked ( return_ref ) ]
254
+ pub ( crate ) fn defaulted_trait_method_rpitit_values (
255
+ db : & dyn HirDatabase ,
256
+ method_id : FunctionId ,
257
+ ) -> ThinVec < ( RpititTraitAssocTyId , Binders < Ty > ) > {
258
+ let method_generics = generics ( db , method_id . into ( ) ) ;
259
+ let mut table = InferenceTable :: new ( db , db . trait_environment ( method_id . into ( ) ) ) ;
253
260
254
- fn interner ( & self ) -> Interner {
255
- Interner
256
- }
261
+ let data = db. function_signature ( method_id) ;
262
+ let resolver = method_id. resolver ( db) ;
263
+ let mut ctx_ret = TyLoweringContext :: new (
264
+ db,
265
+ & resolver,
266
+ & data. store ,
267
+ method_id. into ( ) ,
268
+ LifetimeElisionKind :: Infer ,
269
+ )
270
+ . with_impl_trait_mode ( ImplTraitLoweringMode :: Opaque )
271
+ . with_type_param_mode ( ParamLoweringMode :: Placeholder ) ;
272
+ // This is the return type of the method, with RPITIT lowered as opaques. In other words, like if it was written
273
+ // in an impl.
274
+ let method_opaques_ret = match data. ret_type {
275
+ Some ( ret_type) => ctx_ret. lower_ty ( ret_type) ,
276
+ None => TyKind :: Tuple ( 0 , Substitution :: empty ( Interner ) ) . intern ( Interner ) ,
277
+ } ;
278
+ let method_opaques_ret = table. normalize_associated_types_in ( method_opaques_ret) ;
257
279
258
- fn fold_free_placeholder_ty (
259
- & mut self ,
260
- universe : PlaceholderIndex ,
261
- _outer_binder : DebruijnIndex ,
262
- ) -> Ty {
263
- let placeholder = from_placeholder_idx ( self . db , universe ) ;
264
- if placeholder . parent == self . method {
265
- BoundVar :: new (
266
- DebruijnIndex :: INNERMOST ,
267
- placeholder . local_id . into_raw ( ) . into_u32 ( ) as usize
268
- + self . method_generics . len_lifetimes ( ) ,
269
- )
270
- . to_ty ( Interner )
271
- } else {
272
- TyKind :: Placeholder ( universe ) . intern ( Interner )
273
- }
274
- }
280
+ // This is the return type of the method, with RPITITs lowered as associated types. In other words, like in its
281
+ // signature.
282
+ let method_assocs_ret = db
283
+ . callable_item_signature ( method_id . into ( ) )
284
+ . substitute ( Interner , & method_generics . placeholder_subst ( db ) )
285
+ . ret ( )
286
+ . clone ( ) ;
287
+ let mut rpitit_to_infer_var_folder = RpititToInferVarFolder {
288
+ db ,
289
+ table : & mut table ,
290
+ trait_method_id : method_id ,
291
+ trait_rpitit_to_infer_var : FxHashMap :: default ( ) ,
292
+ } ;
293
+ let method_assocs_ret =
294
+ method_assocs_ret . fold_with ( & mut rpitit_to_infer_var_folder , DebruijnIndex :: INNERMOST ) ;
295
+ let trait_rpitit_to_infer_var = rpitit_to_infer_var_folder . trait_rpitit_to_infer_var ;
296
+ let method_assocs_ret = table . normalize_associated_types_in ( method_assocs_ret ) ;
275
297
276
- fn fold_free_placeholder_const (
277
- & mut self ,
278
- ty : Ty ,
279
- universe : PlaceholderIndex ,
280
- _outer_binder : DebruijnIndex ,
281
- ) -> Const {
282
- let placeholder = from_placeholder_idx ( self . db , universe) ;
283
- if placeholder. parent == self . method {
284
- BoundVar :: new (
285
- DebruijnIndex :: INNERMOST ,
286
- placeholder. local_id . into_raw ( ) . into_u32 ( ) as usize
287
- + self . method_generics . len_lifetimes ( ) ,
288
- )
289
- . to_const ( Interner , ty)
290
- } else {
291
- Const :: new ( Interner , ConstData { ty, value : ConstValue :: Placeholder ( universe) } )
292
- }
293
- }
298
+ table. resolve_obligations_as_possible ( ) ;
299
+ // Even if unification fails, we want to continue. We will fill the RPITITs with error types.
300
+ table. unify ( & method_assocs_ret, & method_opaques_ret) ;
301
+ table. resolve_obligations_as_possible ( ) ;
294
302
295
- fn fold_free_placeholder_lifetime (
296
- & mut self ,
297
- universe : PlaceholderIndex ,
298
- _outer_binder : DebruijnIndex ,
299
- ) -> Lifetime {
300
- let placeholder = lt_from_placeholder_idx ( self . db , universe) ;
301
- if placeholder. parent == self . method {
302
- BoundVar :: new (
303
- DebruijnIndex :: INNERMOST ,
304
- placeholder. local_id . into_raw ( ) . into_u32 ( ) as usize ,
305
- )
306
- . to_lifetime ( Interner )
307
- } else {
308
- Lifetime :: new ( Interner , LifetimeData :: Placeholder ( universe) )
309
- }
310
- }
311
- }
303
+ ThinVec :: from_iter ( trait_rpitit_to_infer_var. into_iter ( ) . map ( |( trait_assoc_id, infer_var) | {
304
+ let trait_assoc = trait_assoc_id. loc ( db) ;
305
+ let rpitit = table. resolve_completely ( infer_var) ;
306
+ let rpitit = rpitit. fold_with (
307
+ & mut PlaceholderToBoundVarFolder {
308
+ db,
309
+ method : method_id. into ( ) ,
310
+ method_generics : method_generics. self_params ( ) ,
311
+ parent : trait_assoc. trait_id . into ( ) ,
312
+ parent_generics : method_generics
313
+ . parent_generics ( )
314
+ . expect ( "method should be inside trait" )
315
+ . self_params ( ) ,
316
+ } ,
317
+ DebruijnIndex :: INNERMOST ,
318
+ ) ;
319
+ let impl_rpitit = trait_assoc. bounds . as_ref ( ) . map ( |_| rpitit) ;
320
+ ( trait_assoc_id, impl_rpitit)
321
+ } ) )
312
322
}
313
323
314
324
fn check_method_generics_are_structurally_compatible (
@@ -333,3 +343,164 @@ fn check_method_generics_are_structurally_compatible(
333
343
334
344
true
335
345
}
346
+
347
+ #[ derive( chalk_derive:: FallibleTypeFolder ) ]
348
+ #[ has_interner( Interner ) ]
349
+ struct RpititToInferVarFolder < ' a , ' b > {
350
+ db : & ' a dyn HirDatabase ,
351
+ table : & ' a mut InferenceTable < ' b > ,
352
+ trait_rpitit_to_infer_var : FxHashMap < RpititTraitAssocTyId , Ty > ,
353
+ trait_method_id : FunctionId ,
354
+ }
355
+ impl TypeFolder < Interner > for RpititToInferVarFolder < ' _ , ' _ > {
356
+ fn as_dyn ( & mut self ) -> & mut dyn TypeFolder < Interner > {
357
+ self
358
+ }
359
+
360
+ fn interner ( & self ) -> Interner {
361
+ Interner
362
+ }
363
+
364
+ fn fold_ty ( & mut self , ty : Ty , outer_binder : DebruijnIndex ) -> Ty {
365
+ let result = match ty. kind ( Interner ) {
366
+ TyKind :: Alias ( AliasTy :: Projection ( ProjectionTy { associated_ty_id, substitution } ) )
367
+ | TyKind :: AssociatedType ( associated_ty_id, substitution) => {
368
+ if let AnyTraitAssocType :: Rpitit ( assoc_id) =
369
+ from_assoc_type_id ( self . db , * associated_ty_id)
370
+ {
371
+ let assoc = assoc_id. loc ( self . db ) ;
372
+ if assoc. synthesized_from_method == self . trait_method_id {
373
+ if let Some ( ty) = self . trait_rpitit_to_infer_var . get ( & assoc_id) {
374
+ return ty. clone ( ) ;
375
+ }
376
+
377
+ // Replace with new infer var.
378
+ // This needs to come before we fold the bounds, because they also contain this associated type.
379
+ let var = self . table . new_type_var ( ) ;
380
+ self . trait_rpitit_to_infer_var . insert ( assoc_id, var. clone ( ) ) ;
381
+
382
+ // Recurse into bounds, so that nested RPITITs will be handled correctly.
383
+ for bound in assoc. bounds . clone ( ) . substitute ( Interner , substitution) {
384
+ let bound = inline_bound_to_generic_predicate ( & bound, var. clone ( ) ) ;
385
+ // This is an unrelated binder, therefore `DebruijnIndex::INNERMOST`.
386
+ let bound = bound. fold_with ( self , DebruijnIndex :: INNERMOST ) ;
387
+ let bound = self . table . normalize_associated_types_in ( bound) ;
388
+ self . table . register_obligation ( Goal :: new (
389
+ Interner ,
390
+ GoalData :: Quantified (
391
+ chalk_ir:: QuantifierKind :: ForAll ,
392
+ bound. map ( |bound| {
393
+ Goal :: new (
394
+ Interner ,
395
+ GoalData :: DomainGoal ( DomainGoal :: Holds ( bound) ) ,
396
+ )
397
+ } ) ,
398
+ ) ,
399
+ ) ) ;
400
+ }
401
+
402
+ return var;
403
+ }
404
+ }
405
+ ty. clone ( )
406
+ }
407
+ _ => ty. clone ( ) ,
408
+ } ;
409
+ result. super_fold_with ( self , outer_binder)
410
+ }
411
+ }
412
+
413
+ #[ derive( chalk_derive:: FallibleTypeFolder ) ]
414
+ #[ has_interner( Interner ) ]
415
+ struct PlaceholderToBoundVarFolder < ' a > {
416
+ db : & ' a dyn HirDatabase ,
417
+ method : GenericDefId ,
418
+ method_generics : & ' a GenericParams ,
419
+ parent : GenericDefId ,
420
+ parent_generics : & ' a GenericParams ,
421
+ }
422
+ impl TypeFolder < Interner > for PlaceholderToBoundVarFolder < ' _ > {
423
+ fn as_dyn ( & mut self ) -> & mut dyn TypeFolder < Interner > {
424
+ self
425
+ }
426
+
427
+ fn interner ( & self ) -> Interner {
428
+ Interner
429
+ }
430
+
431
+ fn fold_free_placeholder_ty (
432
+ & mut self ,
433
+ universe : PlaceholderIndex ,
434
+ _outer_binder : DebruijnIndex ,
435
+ ) -> Ty {
436
+ let placeholder = from_placeholder_idx ( self . db , universe) ;
437
+ if placeholder. parent == self . method {
438
+ BoundVar :: new (
439
+ DebruijnIndex :: INNERMOST ,
440
+ placeholder. local_id . into_raw ( ) . into_u32 ( ) as usize
441
+ + self . method_generics . len_lifetimes ( ) ,
442
+ )
443
+ . to_ty ( Interner )
444
+ } else if placeholder. parent == self . parent {
445
+ BoundVar :: new (
446
+ DebruijnIndex :: INNERMOST ,
447
+ placeholder. local_id . into_raw ( ) . into_u32 ( ) as usize
448
+ + self . method_generics . len ( )
449
+ + self . parent_generics . len_lifetimes ( ) ,
450
+ )
451
+ . to_ty ( Interner )
452
+ } else {
453
+ TyKind :: Placeholder ( universe) . intern ( Interner )
454
+ }
455
+ }
456
+
457
+ fn fold_free_placeholder_const (
458
+ & mut self ,
459
+ ty : Ty ,
460
+ universe : PlaceholderIndex ,
461
+ _outer_binder : DebruijnIndex ,
462
+ ) -> Const {
463
+ let placeholder = from_placeholder_idx ( self . db , universe) ;
464
+ if placeholder. parent == self . method {
465
+ BoundVar :: new (
466
+ DebruijnIndex :: INNERMOST ,
467
+ placeholder. local_id . into_raw ( ) . into_u32 ( ) as usize
468
+ + self . method_generics . len_lifetimes ( ) ,
469
+ )
470
+ . to_const ( Interner , ty)
471
+ } else if placeholder. parent == self . parent {
472
+ BoundVar :: new (
473
+ DebruijnIndex :: INNERMOST ,
474
+ placeholder. local_id . into_raw ( ) . into_u32 ( ) as usize
475
+ + self . method_generics . len ( )
476
+ + self . parent_generics . len_lifetimes ( ) ,
477
+ )
478
+ . to_const ( Interner , ty)
479
+ } else {
480
+ Const :: new ( Interner , ConstData { ty, value : ConstValue :: Placeholder ( universe) } )
481
+ }
482
+ }
483
+
484
+ fn fold_free_placeholder_lifetime (
485
+ & mut self ,
486
+ universe : PlaceholderIndex ,
487
+ _outer_binder : DebruijnIndex ,
488
+ ) -> Lifetime {
489
+ let placeholder = lt_from_placeholder_idx ( self . db , universe) ;
490
+ if placeholder. parent == self . method {
491
+ BoundVar :: new (
492
+ DebruijnIndex :: INNERMOST ,
493
+ placeholder. local_id . into_raw ( ) . into_u32 ( ) as usize ,
494
+ )
495
+ . to_lifetime ( Interner )
496
+ } else if placeholder. parent == self . parent {
497
+ BoundVar :: new (
498
+ DebruijnIndex :: INNERMOST ,
499
+ placeholder. local_id . into_raw ( ) . into_u32 ( ) as usize + self . method_generics . len ( ) ,
500
+ )
501
+ . to_lifetime ( Interner )
502
+ } else {
503
+ Lifetime :: new ( Interner , LifetimeData :: Placeholder ( universe) )
504
+ }
505
+ }
506
+ }
0 commit comments