@@ -6,7 +6,7 @@ use chalk_ir::{
6
6
cast:: { Cast , CastTo , Caster } ,
7
7
fold:: TypeFoldable ,
8
8
interner:: HasInterner ,
9
- AdtId , BoundVar , DebruijnIndex , Scalar ,
9
+ AdtId , DebruijnIndex , Scalar ,
10
10
} ;
11
11
use hir_def:: {
12
12
builtin_type:: BuiltinType , generics:: TypeOrConstParamData , ConstParamId , DefWithBodyId ,
@@ -16,9 +16,9 @@ use smallvec::SmallVec;
16
16
17
17
use crate :: {
18
18
consteval:: unknown_const_as_generic, db:: HirDatabase , infer:: unify:: InferenceTable , primitive,
19
- to_assoc_type_id, to_chalk_trait_id, utils:: generics, Binders , CallableSig , ConstData ,
20
- ConstValue , GenericArg , GenericArgData , Interner , ProjectionTy , Substitution , TraitRef , Ty ,
21
- TyDefId , TyExt , TyKind , ValueTyDefId ,
19
+ to_assoc_type_id, to_chalk_trait_id, utils:: generics, Binders , BoundVar , CallableSig ,
20
+ GenericArg , Interner , ProjectionTy , Substitution , TraitRef , Ty , TyDefId , TyExt , TyKind ,
21
+ ValueTyDefId ,
22
22
} ;
23
23
24
24
#[ derive( Debug , Clone , PartialEq , Eq ) ]
@@ -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
@@ -79,20 +101,12 @@ impl<D> TyBuilder<D> {
79
101
pub fn fill_with_bound_vars ( self , debruijn : DebruijnIndex , starting_from : usize ) -> Self {
80
102
// self.fill is inlined to make borrow checker happy
81
103
let mut this = self ;
82
- let other = this. param_kinds . iter ( ) . skip ( this. vec . len ( ) ) ;
104
+ let other = & this. param_kinds [ this. vec . len ( ) .. ] ;
83
105
let filler = ( starting_from..) . zip ( other) . map ( |( idx, kind) | match kind {
84
- ParamKind :: Type => {
85
- GenericArgData :: Ty ( TyKind :: BoundVar ( BoundVar :: new ( debruijn , idx ) ) . intern ( Interner ) )
86
- . intern ( Interner )
106
+ ParamKind :: Type => BoundVar :: new ( debruijn , idx ) . to_ty ( Interner ) . cast ( Interner ) ,
107
+ ParamKind :: Const ( ty ) => {
108
+ BoundVar :: new ( debruijn , idx ) . to_const ( Interner , ty . clone ( ) ) . cast ( Interner )
87
109
}
88
- ParamKind :: Const ( ty) => GenericArgData :: Const (
89
- ConstData {
90
- value : ConstValue :: BoundVar ( BoundVar :: new ( debruijn, idx) ) ,
91
- ty : ty. clone ( ) ,
92
- }
93
- . intern ( Interner ) ,
94
- )
95
- . intern ( Interner ) ,
96
110
} ) ;
97
111
this. vec . extend ( filler. take ( this. remaining ( ) ) . casted ( Interner ) ) ;
98
112
assert_eq ! ( this. remaining( ) , 0 ) ;
@@ -102,8 +116,8 @@ impl<D> TyBuilder<D> {
102
116
pub fn fill_with_unknown ( self ) -> Self {
103
117
// self.fill is inlined to make borrow checker happy
104
118
let mut this = self ;
105
- let filler = this. param_kinds . iter ( ) . skip ( this. vec . len ( ) ) . map ( |x| match x {
106
- ParamKind :: Type => GenericArgData :: Ty ( TyKind :: Error . intern ( Interner ) ) . intern ( Interner ) ,
119
+ let filler = this. param_kinds [ this. vec . len ( ) .. ] . iter ( ) . map ( |x| match x {
120
+ ParamKind :: Type => TyKind :: Error . intern ( Interner ) . cast ( Interner ) ,
107
121
ParamKind :: Const ( ty) => unknown_const_as_generic ( ty. clone ( ) ) ,
108
122
} ) ;
109
123
this. vec . extend ( filler. casted ( Interner ) ) ;
@@ -113,33 +127,17 @@ impl<D> TyBuilder<D> {
113
127
114
128
pub ( crate ) fn fill_with_inference_vars ( self , table : & mut InferenceTable < ' _ > ) -> Self {
115
129
self . fill ( |x| match x {
116
- ParamKind :: Type => GenericArgData :: Ty ( table. new_type_var ( ) ) . intern ( Interner ) ,
117
- ParamKind :: Const ( ty) => {
118
- GenericArgData :: Const ( table. new_const_var ( ty. clone ( ) ) ) . intern ( Interner )
119
- }
130
+ ParamKind :: Type => table. new_type_var ( ) . cast ( Interner ) ,
131
+ ParamKind :: Const ( ty) => table. new_const_var ( ty. clone ( ) ) . cast ( Interner ) ,
120
132
} )
121
133
}
122
134
123
135
pub fn fill ( mut self , filler : impl FnMut ( & ParamKind ) -> GenericArg ) -> Self {
124
- self . vec . extend ( self . param_kinds . iter ( ) . skip ( self . vec . len ( ) ) . map ( filler) ) ;
136
+ self . vec . extend ( self . param_kinds [ self . vec . len ( ) .. ] . iter ( ) . map ( filler) ) ;
125
137
assert_eq ! ( self . remaining( ) , 0 ) ;
126
138
self
127
139
}
128
140
129
- pub fn use_parent_substs ( mut self , parent_substs : & Substitution ) -> Self {
130
- assert ! ( self . vec. is_empty( ) ) ;
131
- assert ! ( parent_substs. len( Interner ) <= self . param_kinds. len( ) ) ;
132
- self . extend ( parent_substs. iter ( Interner ) . cloned ( ) ) ;
133
- self
134
- }
135
-
136
- fn extend ( & mut self , it : impl Iterator < Item = GenericArg > + Clone ) {
137
- for x in it. clone ( ) . zip ( self . param_kinds . iter ( ) . skip ( self . vec . len ( ) ) ) {
138
- self . assert_match_kind ( & x. 0 , & x. 1 ) ;
139
- }
140
- self . vec . extend ( it) ;
141
- }
142
-
143
141
fn assert_match_kind ( & self , a : & chalk_ir:: GenericArg < Interner > , e : & ParamKind ) {
144
142
match ( a. data ( Interner ) , e) {
145
143
( chalk_ir:: GenericArgData :: Ty ( _) , ParamKind :: Type )
@@ -188,53 +186,44 @@ impl TyBuilder<()> {
188
186
params. placeholder_subst ( db)
189
187
}
190
188
191
- pub fn subst_for_def ( db : & dyn HirDatabase , def : impl Into < GenericDefId > ) -> TyBuilder < ( ) > {
192
- let def = def. into ( ) ;
193
- let params = generics ( db. upcast ( ) , def) ;
194
- TyBuilder :: new (
195
- ( ) ,
196
- params
197
- . iter ( )
198
- . map ( |( id, data) | match data {
199
- TypeOrConstParamData :: TypeParamData ( _) => ParamKind :: Type ,
200
- TypeOrConstParamData :: ConstParamData ( _) => {
201
- ParamKind :: Const ( db. const_param_ty ( ConstParamId :: from_unchecked ( id) ) )
202
- }
203
- } )
204
- . collect ( ) ,
205
- )
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)
206
208
}
207
209
208
210
/// Creates a `TyBuilder` to build `Substitution` for a generator defined in `parent`.
209
211
///
210
212
/// A generator's substitution consists of:
211
- /// - generic parameters in scope on `parent`
212
213
/// - resume type of generator
213
214
/// - yield type of generator ([`Generator::Yield`](std::ops::Generator::Yield))
214
215
/// - return type of generator ([`Generator::Return`](std::ops::Generator::Return))
216
+ /// - generic parameters in scope on `parent`
215
217
/// in this order.
216
218
///
217
219
/// This method prepopulates the builder with placeholder substitution of `parent`, so you
218
220
/// should only push exactly 3 `GenericArg`s before building.
219
221
pub fn subst_for_generator ( db : & dyn HirDatabase , parent : DefWithBodyId ) -> TyBuilder < ( ) > {
220
- let parent_subst = match parent. as_generic_def_id ( ) {
221
- Some ( parent) => generics ( db. upcast ( ) , parent) . placeholder_subst ( db) ,
222
- // Static initializers *may* contain generators.
223
- None => Substitution :: empty ( Interner ) ,
224
- } ;
225
- let builder = TyBuilder :: new (
226
- ( ) ,
227
- parent_subst
228
- . iter ( Interner )
229
- . map ( |arg| match arg. constant ( Interner ) {
230
- Some ( c) => ParamKind :: Const ( c. data ( Interner ) . ty . clone ( ) ) ,
231
- None => ParamKind :: Type ,
232
- } )
233
- // These represent resume type, yield type, and return type of generator.
234
- . chain ( std:: iter:: repeat ( ParamKind :: Type ) . take ( 3 ) )
235
- . collect ( ) ,
236
- ) ;
237
- 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)
238
227
}
239
228
240
229
pub fn build ( self ) -> Substitution {
@@ -245,24 +234,35 @@ impl TyBuilder<()> {
245
234
246
235
impl TyBuilder < hir_def:: AdtId > {
247
236
pub fn adt ( db : & dyn HirDatabase , def : hir_def:: AdtId ) -> TyBuilder < hir_def:: AdtId > {
248
- TyBuilder :: subst_for_def ( db, def) . with_data ( def)
237
+ TyBuilder :: subst_for_def ( db, def, None ) . with_data ( def)
249
238
}
250
239
251
240
pub fn fill_with_defaults (
252
241
mut self ,
253
242
db : & dyn HirDatabase ,
254
243
mut fallback : impl FnMut ( ) -> Ty ,
255
244
) -> Self {
245
+ // Note that we're building ADT, so we never have parent generic parameters.
256
246
let defaults = db. generic_defaults ( self . data . into ( ) ) ;
247
+ let dummy_ty = TyKind :: Error . intern ( Interner ) . cast ( Interner ) ;
257
248
for default_ty in defaults. iter ( ) . skip ( self . vec . len ( ) ) {
258
- if let GenericArgData :: Ty ( x) = default_ty. skip_binders ( ) . data ( Interner ) {
249
+ // NOTE(skip_binders): we only check if the arg type is error type.
250
+ if let Some ( x) = default_ty. skip_binders ( ) . ty ( Interner ) {
259
251
if x. is_unknown ( ) {
260
252
self . vec . push ( fallback ( ) . cast ( Interner ) ) ;
261
253
continue ;
262
254
}
263
- } ;
264
- // each default can depend on the previous parameters
265
- 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
+ ) ;
266
266
self . vec . push ( default_ty. clone ( ) . substitute ( Interner , & subst_so_far) . cast ( Interner ) ) ;
267
267
}
268
268
self
@@ -277,7 +277,7 @@ impl TyBuilder<hir_def::AdtId> {
277
277
pub struct Tuple ( usize ) ;
278
278
impl TyBuilder < Tuple > {
279
279
pub fn tuple ( size : usize ) -> TyBuilder < Tuple > {
280
- TyBuilder :: new ( Tuple ( size) , iter:: repeat ( ParamKind :: Type ) . take ( size) . collect ( ) )
280
+ TyBuilder :: new ( Tuple ( size) , iter:: repeat ( ParamKind :: Type ) . take ( size) . collect ( ) , None )
281
281
}
282
282
283
283
pub fn build ( self ) -> Ty {
@@ -288,7 +288,7 @@ impl TyBuilder<Tuple> {
288
288
289
289
impl TyBuilder < TraitId > {
290
290
pub fn trait_ref ( db : & dyn HirDatabase , def : TraitId ) -> TyBuilder < TraitId > {
291
- TyBuilder :: subst_for_def ( db, def) . with_data ( def)
291
+ TyBuilder :: subst_for_def ( db, def, None ) . with_data ( def)
292
292
}
293
293
294
294
pub fn build ( self ) -> TraitRef {
@@ -298,8 +298,12 @@ impl TyBuilder<TraitId> {
298
298
}
299
299
300
300
impl TyBuilder < TypeAliasId > {
301
- pub fn assoc_type_projection ( db : & dyn HirDatabase , def : TypeAliasId ) -> TyBuilder < TypeAliasId > {
302
- 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)
303
307
}
304
308
305
309
pub fn build ( self ) -> ProjectionTy {
@@ -309,35 +313,48 @@ impl TyBuilder<TypeAliasId> {
309
313
}
310
314
311
315
impl < T : HasInterner < Interner = Interner > + TypeFoldable < Interner > > TyBuilder < Binders < T > > {
312
- fn subst_binders ( b : Binders < T > ) -> Self {
313
- let param_kinds = b
314
- . binders
315
- . iter ( Interner )
316
- . map ( |x| match x {
317
- chalk_ir:: VariableKind :: Ty ( _) => ParamKind :: Type ,
318
- chalk_ir:: VariableKind :: Lifetime => panic ! ( "Got lifetime parameter" ) ,
319
- chalk_ir:: VariableKind :: Const ( ty) => ParamKind :: Const ( ty. clone ( ) ) ,
320
- } )
321
- . collect ( ) ;
322
- TyBuilder :: new ( b, param_kinds)
323
- }
324
-
325
316
pub fn build ( self ) -> T {
326
317
let ( b, subst) = self . build_internal ( ) ;
327
318
b. substitute ( Interner , & subst)
328
319
}
329
320
}
330
321
331
322
impl TyBuilder < Binders < Ty > > {
332
- pub fn def_ty ( db : & dyn HirDatabase , def : TyDefId ) -> TyBuilder < Binders < Ty > > {
333
- 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)
334
338
}
335
339
336
340
pub fn impl_self_ty ( db : & dyn HirDatabase , def : hir_def:: ImplId ) -> TyBuilder < Binders < Ty > > {
337
- TyBuilder :: subst_binders ( db. impl_self_ty ( def) )
341
+ TyBuilder :: subst_for_def ( db , def , None ) . with_data ( db. impl_self_ty ( def) )
338
342
}
339
343
340
- pub fn value_ty ( db : & dyn HirDatabase , def : ValueTyDefId ) -> TyBuilder < Binders < Ty > > {
341
- 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)
342
359
}
343
360
}
0 commit comments