@@ -196,6 +196,9 @@ where
196196 let wg_goal = gb. forall ( & struct_data, ( ) , |gb, _, ( fields, where_clauses) , ( ) | {
197197 let interner = gb. interner ( ) ;
198198
199+ // struct is well-formed in terms of Sized
200+ let sized_constraint_goal = compute_struct_sized_constraint ( gb. db ( ) , fields) ;
201+
199202 // (FromEnv(T: Eq) => ...)
200203 gb. implies (
201204 where_clauses
@@ -209,7 +212,13 @@ where
209212 fields. fold ( gb. interner ( ) , & mut input_types) ;
210213 // ...in a where clause.
211214 where_clauses. fold ( gb. interner ( ) , & mut input_types) ;
212- gb. all ( input_types. into_iter ( ) . map ( |ty| ty. well_formed ( ) ) )
215+
216+ gb. all (
217+ input_types
218+ . into_iter ( )
219+ . map ( |ty| ty. well_formed ( ) . cast ( interner) )
220+ . chain ( sized_constraint_goal. into_iter ( ) ) ,
221+ )
213222 } ,
214223 )
215224 } ) ;
@@ -230,7 +239,14 @@ where
230239
231240 pub fn verify_trait_impl ( & self , impl_id : ImplId < I > ) -> Result < ( ) , WfError < I > > {
232241 let interner = self . db . interner ( ) ;
242+
233243 let impl_datum = self . db . impl_datum ( impl_id) ;
244+ let trait_id = impl_datum. trait_id ( ) ;
245+
246+ // You can't manually implement Sized
247+ if let Some ( WellKnownTrait :: SizedTrait ) = self . db . trait_datum ( trait_id) . well_known {
248+ return Err ( WfError :: IllFormedTraitImpl ( trait_id) ) ;
249+ }
234250
235251 let impl_goal = Goal :: all (
236252 interner,
@@ -256,8 +272,7 @@ where
256272 if is_legal {
257273 Ok ( ( ) )
258274 } else {
259- let trait_ref = & impl_datum. binders . value . trait_ref ;
260- Err ( WfError :: IllFormedTraitImpl ( trait_ref. trait_id ) )
275+ Err ( WfError :: IllFormedTraitImpl ( trait_id) )
261276 }
262277 }
263278}
@@ -470,3 +485,30 @@ fn compute_assoc_ty_goal<I: Interner>(
470485 } ,
471486 ) )
472487}
488+
489+ /// Computes a goal to prove Sized constraints on a struct definition.
490+ /// Struct is considered well-formed (in terms of Sized) when it either
491+ /// has no fields or all of it's fields except the last are proven to be Sized.
492+ fn compute_struct_sized_constraint < I : Interner > (
493+ db : & dyn RustIrDatabase < I > ,
494+ fields : & [ Ty < I > ] ,
495+ ) -> Option < Goal < I > > {
496+ if fields. len ( ) <= 1 {
497+ return None ;
498+ }
499+
500+ let interner = db. interner ( ) ;
501+
502+ let sized_trait = db. well_known_trait_id ( WellKnownTrait :: SizedTrait ) ;
503+
504+ Some ( Goal :: all (
505+ interner,
506+ fields[ ..fields. len ( ) - 1 ] . iter ( ) . map ( |ty| {
507+ TraitRef {
508+ trait_id : sized_trait,
509+ substitution : Substitution :: from1 ( interner, ty. clone ( ) ) ,
510+ }
511+ . cast ( interner)
512+ } ) ,
513+ ) )
514+ }
0 commit comments