@@ -34,31 +34,51 @@ pub struct TyBuilder<D> {
34
34
data : D ,
35
35
vec : SmallVec < [ GenericArg ; 2 ] > ,
36
36
param_kinds : SmallVec < [ ParamKind ; 2 ] > ,
37
+ parent_subst : Substitution ,
37
38
}
38
39
39
40
impl < A > TyBuilder < A > {
40
41
fn with_data < B > ( self , data : B ) -> TyBuilder < B > {
41
- TyBuilder { data, param_kinds : self . param_kinds , vec : self . vec }
42
+ TyBuilder {
43
+ data,
44
+ vec : self . vec ,
45
+ param_kinds : self . param_kinds ,
46
+ parent_subst : self . parent_subst ,
47
+ }
42
48
}
43
49
}
44
50
45
51
impl < D > TyBuilder < D > {
46
- fn new ( data : D , param_kinds : SmallVec < [ ParamKind ; 2 ] > ) -> TyBuilder < D > {
47
- TyBuilder { data, vec : SmallVec :: with_capacity ( param_kinds. len ( ) ) , param_kinds }
52
+ fn new (
53
+ data : D ,
54
+ param_kinds : SmallVec < [ ParamKind ; 2 ] > ,
55
+ parent_subst : Option < Substitution > ,
56
+ ) -> Self {
57
+ let parent_subst = parent_subst. unwrap_or_else ( || Substitution :: empty ( Interner ) ) ;
58
+ Self { data, vec : SmallVec :: with_capacity ( param_kinds. len ( ) ) , param_kinds, parent_subst }
59
+ }
60
+
61
+ fn new_empty ( data : D ) -> Self {
62
+ TyBuilder :: new ( data, SmallVec :: new ( ) , None )
48
63
}
49
64
50
65
fn build_internal ( self ) -> ( D , Substitution ) {
51
66
assert_eq ! ( self . vec. len( ) , self . param_kinds. len( ) ) ;
52
67
for ( a, e) in self . vec . iter ( ) . zip ( self . param_kinds . iter ( ) ) {
53
68
self . assert_match_kind ( a, e) ;
54
69
}
55
- let subst = Substitution :: from_iter ( Interner , self . vec ) ;
70
+ let subst = Substitution :: from_iter (
71
+ Interner ,
72
+ self . vec . into_iter ( ) . chain ( self . parent_subst . iter ( Interner ) . cloned ( ) ) ,
73
+ ) ;
56
74
( self . data , subst)
57
75
}
58
76
59
77
pub fn push ( mut self , arg : impl CastTo < GenericArg > ) -> Self {
78
+ assert ! ( self . remaining( ) > 0 ) ;
60
79
let arg = arg. cast ( Interner ) ;
61
80
let expected_kind = & self . param_kinds [ self . vec . len ( ) ] ;
81
+
62
82
let arg_kind = match arg. data ( Interner ) {
63
83
chalk_ir:: GenericArgData :: Ty ( _) => ParamKind :: Type ,
64
84
chalk_ir:: GenericArgData :: Lifetime ( _) => panic ! ( "Got lifetime in TyBuilder::push" ) ,
@@ -68,7 +88,9 @@ impl<D> TyBuilder<D> {
68
88
}
69
89
} ;
70
90
assert_eq ! ( * expected_kind, arg_kind) ;
91
+
71
92
self . vec . push ( arg) ;
93
+
72
94
self
73
95
}
74
96
@@ -116,20 +138,6 @@ impl<D> TyBuilder<D> {
116
138
self
117
139
}
118
140
119
- pub fn use_parent_substs ( mut self , parent_substs : & Substitution ) -> Self {
120
- assert ! ( self . vec. is_empty( ) ) ;
121
- assert ! ( parent_substs. len( Interner ) <= self . param_kinds. len( ) ) ;
122
- self . extend ( parent_substs. iter ( Interner ) . cloned ( ) ) ;
123
- self
124
- }
125
-
126
- fn extend ( & mut self , it : impl Iterator < Item = GenericArg > + Clone ) {
127
- for x in it. clone ( ) . zip ( self . param_kinds . iter ( ) . skip ( self . vec . len ( ) ) ) {
128
- self . assert_match_kind ( & x. 0 , & x. 1 ) ;
129
- }
130
- self . vec . extend ( it) ;
131
- }
132
-
133
141
fn assert_match_kind ( & self , a : & chalk_ir:: GenericArg < Interner > , e : & ParamKind ) {
134
142
match ( a. data ( Interner ) , e) {
135
143
( chalk_ir:: GenericArgData :: Ty ( _) , ParamKind :: Type )
@@ -178,53 +186,44 @@ impl TyBuilder<()> {
178
186
params. placeholder_subst ( db)
179
187
}
180
188
181
- pub fn subst_for_def ( db : & dyn HirDatabase , def : impl Into < GenericDefId > ) -> TyBuilder < ( ) > {
182
- let def = def. into ( ) ;
183
- let params = generics ( db. upcast ( ) , def) ;
184
- TyBuilder :: new (
185
- ( ) ,
186
- params
187
- . iter ( )
188
- . map ( |( id, data) | match data {
189
- TypeOrConstParamData :: TypeParamData ( _) => ParamKind :: Type ,
190
- TypeOrConstParamData :: ConstParamData ( _) => {
191
- ParamKind :: Const ( db. const_param_ty ( ConstParamId :: from_unchecked ( id) ) )
192
- }
193
- } )
194
- . collect ( ) ,
195
- )
189
+ pub fn subst_for_def (
190
+ db : & dyn HirDatabase ,
191
+ def : impl Into < GenericDefId > ,
192
+ parent_subst : Option < Substitution > ,
193
+ ) -> TyBuilder < ( ) > {
194
+ let generics = generics ( db. upcast ( ) , def. into ( ) ) ;
195
+ // FIXME: this assertion should hold but some adjustment around
196
+ // `ValueTyDefId::EnumVariantId` is needed.
197
+ // assert!(generics.parent_generics().is_some() == parent_subst.is_some());
198
+ let params = generics
199
+ . iter_self ( )
200
+ . map ( |( id, data) | match data {
201
+ TypeOrConstParamData :: TypeParamData ( _) => ParamKind :: Type ,
202
+ TypeOrConstParamData :: ConstParamData ( _) => {
203
+ ParamKind :: Const ( db. const_param_ty ( ConstParamId :: from_unchecked ( id) ) )
204
+ }
205
+ } )
206
+ . collect ( ) ;
207
+ TyBuilder :: new ( ( ) , params, parent_subst)
196
208
}
197
209
198
210
/// Creates a `TyBuilder` to build `Substitution` for a generator defined in `parent`.
199
211
///
200
212
/// A generator's substitution consists of:
201
- /// - generic parameters in scope on `parent`
202
213
/// - resume type of generator
203
214
/// - yield type of generator ([`Generator::Yield`](std::ops::Generator::Yield))
204
215
/// - return type of generator ([`Generator::Return`](std::ops::Generator::Return))
216
+ /// - generic parameters in scope on `parent`
205
217
/// in this order.
206
218
///
207
219
/// This method prepopulates the builder with placeholder substitution of `parent`, so you
208
220
/// should only push exactly 3 `GenericArg`s before building.
209
221
pub fn subst_for_generator ( db : & dyn HirDatabase , parent : DefWithBodyId ) -> TyBuilder < ( ) > {
210
- let parent_subst = match parent. as_generic_def_id ( ) {
211
- Some ( parent) => generics ( db. upcast ( ) , parent) . placeholder_subst ( db) ,
212
- // Static initializers *may* contain generators.
213
- None => Substitution :: empty ( Interner ) ,
214
- } ;
215
- let builder = TyBuilder :: new (
216
- ( ) ,
217
- parent_subst
218
- . iter ( Interner )
219
- . map ( |arg| match arg. constant ( Interner ) {
220
- Some ( c) => ParamKind :: Const ( c. data ( Interner ) . ty . clone ( ) ) ,
221
- None => ParamKind :: Type ,
222
- } )
223
- // These represent resume type, yield type, and return type of generator.
224
- . chain ( std:: iter:: repeat ( ParamKind :: Type ) . take ( 3 ) )
225
- . collect ( ) ,
226
- ) ;
227
- builder. use_parent_substs ( & parent_subst)
222
+ let parent_subst =
223
+ parent. as_generic_def_id ( ) . map ( |p| generics ( db. upcast ( ) , p) . placeholder_subst ( db) ) ;
224
+ // These represent resume type, yield type, and return type of generator.
225
+ let params = std:: iter:: repeat ( ParamKind :: Type ) . take ( 3 ) . collect ( ) ;
226
+ TyBuilder :: new ( ( ) , params, parent_subst)
228
227
}
229
228
230
229
pub fn build ( self ) -> Substitution {
@@ -235,25 +234,35 @@ impl TyBuilder<()> {
235
234
236
235
impl TyBuilder < hir_def:: AdtId > {
237
236
pub fn adt ( db : & dyn HirDatabase , def : hir_def:: AdtId ) -> TyBuilder < hir_def:: AdtId > {
238
- TyBuilder :: subst_for_def ( db, def) . with_data ( def)
237
+ TyBuilder :: subst_for_def ( db, def, None ) . with_data ( def)
239
238
}
240
239
241
240
pub fn fill_with_defaults (
242
241
mut self ,
243
242
db : & dyn HirDatabase ,
244
243
mut fallback : impl FnMut ( ) -> Ty ,
245
244
) -> Self {
245
+ // Note that we're building ADT, so we never have parent generic parameters.
246
246
let defaults = db. generic_defaults ( self . data . into ( ) ) ;
247
+ let dummy_ty = TyKind :: Error . intern ( Interner ) . cast ( Interner ) ;
247
248
for default_ty in defaults. iter ( ) . skip ( self . vec . len ( ) ) {
248
249
// NOTE(skip_binders): we only check if the arg type is error type.
249
250
if let Some ( x) = default_ty. skip_binders ( ) . ty ( Interner ) {
250
251
if x. is_unknown ( ) {
251
252
self . vec . push ( fallback ( ) . cast ( Interner ) ) ;
252
253
continue ;
253
254
}
254
- } ;
255
- // each default can depend on the previous parameters
256
- let subst_so_far = Substitution :: from_iter ( Interner , self . vec . clone ( ) ) ;
255
+ }
256
+ // Each default can only depend on the previous parameters.
257
+ // FIXME: we don't handle const generics here.
258
+ let subst_so_far = Substitution :: from_iter (
259
+ Interner ,
260
+ self . vec
261
+ . iter ( )
262
+ . cloned ( )
263
+ . chain ( iter:: repeat ( dummy_ty. clone ( ) ) )
264
+ . take ( self . param_kinds . len ( ) ) ,
265
+ ) ;
257
266
self . vec . push ( default_ty. clone ( ) . substitute ( Interner , & subst_so_far) . cast ( Interner ) ) ;
258
267
}
259
268
self
@@ -268,7 +277,7 @@ impl TyBuilder<hir_def::AdtId> {
268
277
pub struct Tuple ( usize ) ;
269
278
impl TyBuilder < Tuple > {
270
279
pub fn tuple ( size : usize ) -> TyBuilder < Tuple > {
271
- TyBuilder :: new ( Tuple ( size) , iter:: repeat ( ParamKind :: Type ) . take ( size) . collect ( ) )
280
+ TyBuilder :: new ( Tuple ( size) , iter:: repeat ( ParamKind :: Type ) . take ( size) . collect ( ) , None )
272
281
}
273
282
274
283
pub fn build ( self ) -> Ty {
@@ -279,7 +288,7 @@ impl TyBuilder<Tuple> {
279
288
280
289
impl TyBuilder < TraitId > {
281
290
pub fn trait_ref ( db : & dyn HirDatabase , def : TraitId ) -> TyBuilder < TraitId > {
282
- TyBuilder :: subst_for_def ( db, def) . with_data ( def)
291
+ TyBuilder :: subst_for_def ( db, def, None ) . with_data ( def)
283
292
}
284
293
285
294
pub fn build ( self ) -> TraitRef {
@@ -289,8 +298,12 @@ impl TyBuilder<TraitId> {
289
298
}
290
299
291
300
impl TyBuilder < TypeAliasId > {
292
- pub fn assoc_type_projection ( db : & dyn HirDatabase , def : TypeAliasId ) -> TyBuilder < TypeAliasId > {
293
- TyBuilder :: subst_for_def ( db, def) . with_data ( def)
301
+ pub fn assoc_type_projection (
302
+ db : & dyn HirDatabase ,
303
+ def : TypeAliasId ,
304
+ parent_subst : Option < Substitution > ,
305
+ ) -> TyBuilder < TypeAliasId > {
306
+ TyBuilder :: subst_for_def ( db, def, parent_subst) . with_data ( def)
294
307
}
295
308
296
309
pub fn build ( self ) -> ProjectionTy {
@@ -300,35 +313,48 @@ impl TyBuilder<TypeAliasId> {
300
313
}
301
314
302
315
impl < T : HasInterner < Interner = Interner > + TypeFoldable < Interner > > TyBuilder < Binders < T > > {
303
- fn subst_binders ( b : Binders < T > ) -> Self {
304
- let param_kinds = b
305
- . binders
306
- . iter ( Interner )
307
- . map ( |x| match x {
308
- chalk_ir:: VariableKind :: Ty ( _) => ParamKind :: Type ,
309
- chalk_ir:: VariableKind :: Lifetime => panic ! ( "Got lifetime parameter" ) ,
310
- chalk_ir:: VariableKind :: Const ( ty) => ParamKind :: Const ( ty. clone ( ) ) ,
311
- } )
312
- . collect ( ) ;
313
- TyBuilder :: new ( b, param_kinds)
314
- }
315
-
316
316
pub fn build ( self ) -> T {
317
317
let ( b, subst) = self . build_internal ( ) ;
318
318
b. substitute ( Interner , & subst)
319
319
}
320
320
}
321
321
322
322
impl TyBuilder < Binders < Ty > > {
323
- pub fn def_ty ( db : & dyn HirDatabase , def : TyDefId ) -> TyBuilder < Binders < Ty > > {
324
- TyBuilder :: subst_binders ( db. ty ( def) )
323
+ pub fn def_ty (
324
+ db : & dyn HirDatabase ,
325
+ def : TyDefId ,
326
+ parent_subst : Option < Substitution > ,
327
+ ) -> TyBuilder < Binders < Ty > > {
328
+ let poly_ty = db. ty ( def) ;
329
+ let id: GenericDefId = match def {
330
+ TyDefId :: BuiltinType ( _) => {
331
+ assert ! ( parent_subst. is_none( ) ) ;
332
+ return TyBuilder :: new_empty ( poly_ty) ;
333
+ }
334
+ TyDefId :: AdtId ( id) => id. into ( ) ,
335
+ TyDefId :: TypeAliasId ( id) => id. into ( ) ,
336
+ } ;
337
+ TyBuilder :: subst_for_def ( db, id, parent_subst) . with_data ( poly_ty)
325
338
}
326
339
327
340
pub fn impl_self_ty ( db : & dyn HirDatabase , def : hir_def:: ImplId ) -> TyBuilder < Binders < Ty > > {
328
- TyBuilder :: subst_binders ( db. impl_self_ty ( def) )
341
+ TyBuilder :: subst_for_def ( db , def , None ) . with_data ( db. impl_self_ty ( def) )
329
342
}
330
343
331
- pub fn value_ty ( db : & dyn HirDatabase , def : ValueTyDefId ) -> TyBuilder < Binders < Ty > > {
332
- TyBuilder :: subst_binders ( db. value_ty ( def) )
344
+ pub fn value_ty (
345
+ db : & dyn HirDatabase ,
346
+ def : ValueTyDefId ,
347
+ parent_subst : Option < Substitution > ,
348
+ ) -> TyBuilder < Binders < Ty > > {
349
+ let poly_value_ty = db. value_ty ( def) ;
350
+ let id = match def. to_generic_def_id ( ) {
351
+ Some ( id) => id,
352
+ None => {
353
+ // static items
354
+ assert ! ( parent_subst. is_none( ) ) ;
355
+ return TyBuilder :: new_empty ( poly_value_ty) ;
356
+ }
357
+ } ;
358
+ TyBuilder :: subst_for_def ( db, id, parent_subst) . with_data ( poly_value_ty)
333
359
}
334
360
}
0 commit comments