@@ -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
@@ -116,20 +138,6 @@ impl<D> TyBuilder<D> {
116138 self
117139 }
118140
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-
133141 fn assert_match_kind ( & self , a : & chalk_ir:: GenericArg < Interner > , e : & ParamKind ) {
134142 match ( a. data ( Interner ) , e) {
135143 ( chalk_ir:: GenericArgData :: Ty ( _) , ParamKind :: Type )
@@ -178,53 +186,44 @@ impl TyBuilder<()> {
178186 params. placeholder_subst ( db)
179187 }
180188
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)
196208 }
197209
198210 /// Creates a `TyBuilder` to build `Substitution` for a generator defined in `parent`.
199211 ///
200212 /// A generator's substitution consists of:
201- /// - generic parameters in scope on `parent`
202213 /// - resume type of generator
203214 /// - yield type of generator ([`Generator::Yield`](std::ops::Generator::Yield))
204215 /// - return type of generator ([`Generator::Return`](std::ops::Generator::Return))
216+ /// - generic parameters in scope on `parent`
205217 /// in this order.
206218 ///
207219 /// This method prepopulates the builder with placeholder substitution of `parent`, so you
208220 /// should only push exactly 3 `GenericArg`s before building.
209221 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)
228227 }
229228
230229 pub fn build ( self ) -> Substitution {
@@ -235,25 +234,35 @@ impl TyBuilder<()> {
235234
236235impl TyBuilder < hir_def:: AdtId > {
237236 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)
239238 }
240239
241240 pub fn fill_with_defaults (
242241 mut self ,
243242 db : & dyn HirDatabase ,
244243 mut fallback : impl FnMut ( ) -> Ty ,
245244 ) -> Self {
245+ // Note that we're building ADT, so we never have parent generic parameters.
246246 let defaults = db. generic_defaults ( self . data . into ( ) ) ;
247+ let dummy_ty = TyKind :: Error . intern ( Interner ) . cast ( Interner ) ;
247248 for default_ty in defaults. iter ( ) . skip ( self . vec . len ( ) ) {
248249 // NOTE(skip_binders): we only check if the arg type is error type.
249250 if let Some ( x) = default_ty. skip_binders ( ) . ty ( Interner ) {
250251 if x. is_unknown ( ) {
251252 self . vec . push ( fallback ( ) . cast ( Interner ) ) ;
252253 continue ;
253254 }
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+ ) ;
257266 self . vec . push ( default_ty. clone ( ) . substitute ( Interner , & subst_so_far) . cast ( Interner ) ) ;
258267 }
259268 self
@@ -268,7 +277,7 @@ impl TyBuilder<hir_def::AdtId> {
268277pub struct Tuple ( usize ) ;
269278impl TyBuilder < Tuple > {
270279 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 )
272281 }
273282
274283 pub fn build ( self ) -> Ty {
@@ -279,7 +288,7 @@ impl TyBuilder<Tuple> {
279288
280289impl TyBuilder < TraitId > {
281290 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)
283292 }
284293
285294 pub fn build ( self ) -> TraitRef {
@@ -289,8 +298,12 @@ impl TyBuilder<TraitId> {
289298}
290299
291300impl 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)
294307 }
295308
296309 pub fn build ( self ) -> ProjectionTy {
@@ -300,35 +313,48 @@ impl TyBuilder<TypeAliasId> {
300313}
301314
302315impl < 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-
316316 pub fn build ( self ) -> T {
317317 let ( b, subst) = self . build_internal ( ) ;
318318 b. substitute ( Interner , & subst)
319319 }
320320}
321321
322322impl 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)
325338 }
326339
327340 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) )
329342 }
330343
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)
333359 }
334360}
0 commit comments