11use std:: iter;
22
3+ use crate :: clauses:: builtin_traits:: needs_impl_for_tys;
34use crate :: clauses:: ClauseBuilder ;
45use crate :: { Interner , RustIrDatabase , TraitRef } ;
5- use chalk_ir:: { ApplicationTy , Substitution , TyData , TypeName } ;
6+ use chalk_ir:: { ApplicationTy , StructId , Substitution , TyData , TypeName } ;
67
7- pub fn add_sized_program_clauses < I : Interner > (
8+ fn push_struct_sized_conditions < I : Interner > (
89 db : & dyn RustIrDatabase < I > ,
910 builder : & mut ClauseBuilder < ' _ , I > ,
1011 trait_ref : & TraitRef < I > ,
11- ty : & TyData < I > ,
12+ struct_id : StructId < I > ,
13+ substitution : & Substitution < I > ,
1214) {
13- let interner = db. interner ( ) ;
14-
15- let ( struct_id, substitution) = match ty {
16- TyData :: Apply ( ApplicationTy {
17- name : TypeName :: Struct ( struct_id) ,
18- substitution,
19- } ) => ( * struct_id, substitution) ,
20- // TODO(areredify)
21- // when #368 lands, extend this to handle everything accordingly
22- _ => return ,
23- } ;
24-
2515 let struct_datum = db. struct_datum ( struct_id) ;
2616
2717 // Structs with no fields are always Sized
@@ -30,16 +20,66 @@ pub fn add_sized_program_clauses<I: Interner>(
3020 return ;
3121 }
3222
23+ let interner = db. interner ( ) ;
24+
3325 // To check if a struct type S<..> is Sized, we only have to look at its last field.
3426 // This is because the WF checks for structs require that all the other fields must be Sized.
3527 let last_field_ty = struct_datum
3628 . binders
3729 . map_ref ( |b| b. fields . last ( ) . unwrap ( ) )
3830 . substitute ( interner, substitution) ;
3931
40- let last_field_sized_goal = TraitRef {
41- trait_id : trait_ref. trait_id ,
42- substitution : Substitution :: from1 ( interner, last_field_ty) ,
43- } ;
44- builder. push_clause ( trait_ref. clone ( ) , iter:: once ( last_field_sized_goal) ) ;
32+ needs_impl_for_tys ( db, builder, trait_ref, iter:: once ( last_field_ty) ) ;
33+ }
34+
35+ fn push_tuple_sized_conditions < I : Interner > (
36+ db : & dyn RustIrDatabase < I > ,
37+ builder : & mut ClauseBuilder < ' _ , I > ,
38+ trait_ref : & TraitRef < I > ,
39+ arity : usize ,
40+ substitution : & Substitution < I > ,
41+ ) {
42+ // Empty tuples are always Sized
43+ if arity == 0 {
44+ builder. push_fact ( trait_ref. clone ( ) ) ;
45+ return ;
46+ }
47+
48+ let interner = db. interner ( ) ;
49+
50+ // To check if a tuple is Sized, we only have to look at its last element.
51+ // This is because the WF checks for tuples require that all the other elements must be Sized.
52+ let last_elem_ty = substitution
53+ . iter ( interner)
54+ . last ( )
55+ . unwrap ( )
56+ . ty ( interner)
57+ . unwrap ( )
58+ . clone ( ) ;
59+
60+ needs_impl_for_tys ( db, builder, trait_ref, iter:: once ( last_elem_ty) ) ;
61+ }
62+
63+ pub fn add_sized_program_clauses < I : Interner > (
64+ db : & dyn RustIrDatabase < I > ,
65+ builder : & mut ClauseBuilder < ' _ , I > ,
66+ trait_ref : & TraitRef < I > ,
67+ ty : & TyData < I > ,
68+ ) {
69+ match ty {
70+ TyData :: Apply ( ApplicationTy { name, substitution } ) => match name {
71+ TypeName :: Struct ( struct_id) => {
72+ push_struct_sized_conditions ( db, builder, trait_ref, * struct_id, substitution)
73+ }
74+ TypeName :: Scalar ( _) => builder. push_fact ( trait_ref. clone ( ) ) ,
75+ TypeName :: Tuple ( arity) => {
76+ push_tuple_sized_conditions ( db, builder, trait_ref, * arity, substitution)
77+ }
78+ _ => return ,
79+ } ,
80+ TyData :: Function ( _) => builder. push_fact ( trait_ref. clone ( ) ) ,
81+ // TODO(areredify)
82+ // when #368 lands, extend this to handle everything accordingly
83+ _ => return ,
84+ }
4585}
0 commit comments