@@ -196,6 +196,9 @@ where
196
196
let wg_goal = gb. forall ( & struct_data, ( ) , |gb, _, ( fields, where_clauses) , ( ) | {
197
197
let interner = gb. interner ( ) ;
198
198
199
+ // struct is well-formed in terms of Sized
200
+ let sized_constraint_goal = compute_struct_sized_constraint ( gb. db ( ) , fields) ;
201
+
199
202
// (FromEnv(T: Eq) => ...)
200
203
gb. implies (
201
204
where_clauses
@@ -209,7 +212,13 @@ where
209
212
fields. fold ( gb. interner ( ) , & mut input_types) ;
210
213
// ...in a where clause.
211
214
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
+ )
213
222
} ,
214
223
)
215
224
} ) ;
@@ -230,7 +239,14 @@ where
230
239
231
240
pub fn verify_trait_impl ( & self , impl_id : ImplId < I > ) -> Result < ( ) , WfError < I > > {
232
241
let interner = self . db . interner ( ) ;
242
+
233
243
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
+ }
234
250
235
251
let impl_goal = Goal :: all (
236
252
interner,
@@ -256,8 +272,7 @@ where
256
272
if is_legal {
257
273
Ok ( ( ) )
258
274
} 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) )
261
276
}
262
277
}
263
278
}
@@ -470,3 +485,30 @@ fn compute_assoc_ty_goal<I: Interner>(
470
485
} ,
471
486
) )
472
487
}
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