@@ -6,7 +6,7 @@ use chalk_ir::{
66 cast:: { Cast , CastTo , Caster } ,
77 fold:: TypeFoldable ,
88 interner:: HasInterner ,
9- AdtId , BoundVar , DebruijnIndex , Scalar ,
9+ AdtId , DebruijnIndex , Scalar ,
1010} ;
1111use hir_def:: {
1212 builtin_type:: BuiltinType , generics:: TypeOrConstParamData , ConstParamId , DefWithBodyId ,
@@ -16,9 +16,9 @@ use smallvec::SmallVec;
1616
1717use crate :: {
1818 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 ,
2222} ;
2323
2424#[ derive( Debug , Clone , PartialEq , Eq ) ]
@@ -34,31 +34,51 @@ pub struct TyBuilder<D> {
3434 data : D ,
3535 vec : SmallVec < [ GenericArg ; 2 ] > ,
3636 param_kinds : SmallVec < [ ParamKind ; 2 ] > ,
37+ parent_subst : Substitution ,
3738}
3839
3940impl < A > TyBuilder < A > {
4041 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+ }
4248 }
4349}
4450
4551impl < 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 )
4863 }
4964
5065 fn build_internal ( self ) -> ( D , Substitution ) {
5166 assert_eq ! ( self . vec. len( ) , self . param_kinds. len( ) ) ;
5267 for ( a, e) in self . vec . iter ( ) . zip ( self . param_kinds . iter ( ) ) {
5368 self . assert_match_kind ( a, e) ;
5469 }
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+ ) ;
5674 ( self . data , subst)
5775 }
5876
5977 pub fn push ( mut self , arg : impl CastTo < GenericArg > ) -> Self {
78+ assert ! ( self . remaining( ) > 0 ) ;
6079 let arg = arg. cast ( Interner ) ;
6180 let expected_kind = & self . param_kinds [ self . vec . len ( ) ] ;
81+
6282 let arg_kind = match arg. data ( Interner ) {
6383 chalk_ir:: GenericArgData :: Ty ( _) => ParamKind :: Type ,
6484 chalk_ir:: GenericArgData :: Lifetime ( _) => panic ! ( "Got lifetime in TyBuilder::push" ) ,
@@ -68,7 +88,9 @@ impl<D> TyBuilder<D> {
6888 }
6989 } ;
7090 assert_eq ! ( * expected_kind, arg_kind) ;
91+
7192 self . vec . push ( arg) ;
93+
7294 self
7395 }
7496
@@ -79,20 +101,12 @@ impl<D> TyBuilder<D> {
79101 pub fn fill_with_bound_vars ( self , debruijn : DebruijnIndex , starting_from : usize ) -> Self {
80102 // self.fill is inlined to make borrow checker happy
81103 let mut this = self ;
82- let other = this. param_kinds . iter ( ) . skip ( this. vec . len ( ) ) ;
104+ let other = & this. param_kinds [ this. vec . len ( ) .. ] ;
83105 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 )
87109 }
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 ) ,
96110 } ) ;
97111 this. vec . extend ( filler. take ( this. remaining ( ) ) . casted ( Interner ) ) ;
98112 assert_eq ! ( this. remaining( ) , 0 ) ;
@@ -102,8 +116,8 @@ impl<D> TyBuilder<D> {
102116 pub fn fill_with_unknown ( self ) -> Self {
103117 // self.fill is inlined to make borrow checker happy
104118 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 ) ,
107121 ParamKind :: Const ( ty) => unknown_const_as_generic ( ty. clone ( ) ) ,
108122 } ) ;
109123 this. vec . extend ( filler. casted ( Interner ) ) ;
@@ -113,33 +127,17 @@ impl<D> TyBuilder<D> {
113127
114128 pub ( crate ) fn fill_with_inference_vars ( self , table : & mut InferenceTable < ' _ > ) -> Self {
115129 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 ) ,
120132 } )
121133 }
122134
123135 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) ) ;
125137 assert_eq ! ( self . remaining( ) , 0 ) ;
126138 self
127139 }
128140
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-
143141 fn assert_match_kind ( & self , a : & chalk_ir:: GenericArg < Interner > , e : & ParamKind ) {
144142 match ( a. data ( Interner ) , e) {
145143 ( chalk_ir:: GenericArgData :: Ty ( _) , ParamKind :: Type )
@@ -188,53 +186,44 @@ impl TyBuilder<()> {
188186 params. placeholder_subst ( db)
189187 }
190188
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)
206208 }
207209
208210 /// Creates a `TyBuilder` to build `Substitution` for a generator defined in `parent`.
209211 ///
210212 /// A generator's substitution consists of:
211- /// - generic parameters in scope on `parent`
212213 /// - resume type of generator
213214 /// - yield type of generator ([`Generator::Yield`](std::ops::Generator::Yield))
214215 /// - return type of generator ([`Generator::Return`](std::ops::Generator::Return))
216+ /// - generic parameters in scope on `parent`
215217 /// in this order.
216218 ///
217219 /// This method prepopulates the builder with placeholder substitution of `parent`, so you
218220 /// should only push exactly 3 `GenericArg`s before building.
219221 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)
238227 }
239228
240229 pub fn build ( self ) -> Substitution {
@@ -245,24 +234,35 @@ impl TyBuilder<()> {
245234
246235impl TyBuilder < hir_def:: AdtId > {
247236 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)
249238 }
250239
251240 pub fn fill_with_defaults (
252241 mut self ,
253242 db : & dyn HirDatabase ,
254243 mut fallback : impl FnMut ( ) -> Ty ,
255244 ) -> Self {
245+ // Note that we're building ADT, so we never have parent generic parameters.
256246 let defaults = db. generic_defaults ( self . data . into ( ) ) ;
247+ let dummy_ty = TyKind :: Error . intern ( Interner ) . cast ( Interner ) ;
257248 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 ) {
259251 if x. is_unknown ( ) {
260252 self . vec . push ( fallback ( ) . cast ( Interner ) ) ;
261253 continue ;
262254 }
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+ ) ;
266266 self . vec . push ( default_ty. clone ( ) . substitute ( Interner , & subst_so_far) . cast ( Interner ) ) ;
267267 }
268268 self
@@ -277,7 +277,7 @@ impl TyBuilder<hir_def::AdtId> {
277277pub struct Tuple ( usize ) ;
278278impl TyBuilder < Tuple > {
279279 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 )
281281 }
282282
283283 pub fn build ( self ) -> Ty {
@@ -288,7 +288,7 @@ impl TyBuilder<Tuple> {
288288
289289impl TyBuilder < TraitId > {
290290 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)
292292 }
293293
294294 pub fn build ( self ) -> TraitRef {
@@ -298,8 +298,12 @@ impl TyBuilder<TraitId> {
298298}
299299
300300impl 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)
303307 }
304308
305309 pub fn build ( self ) -> ProjectionTy {
@@ -309,35 +313,48 @@ impl TyBuilder<TypeAliasId> {
309313}
310314
311315impl < 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-
325316 pub fn build ( self ) -> T {
326317 let ( b, subst) = self . build_internal ( ) ;
327318 b. substitute ( Interner , & subst)
328319 }
329320}
330321
331322impl 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)
334338 }
335339
336340 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) )
338342 }
339343
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)
342359 }
343360}
0 commit comments