@@ -308,7 +308,7 @@ impl<'a, Ty> TyLayout<'a, Ty> {
308
308
309
309
Abi :: ScalarPair ( ..) | Abi :: Aggregate { .. } => {
310
310
// Helper for computing `homogenous_aggregate`, allowing a custom
311
- // starting offset (TODO(eddyb): use this to handle variants).
311
+ // starting offset (used below for handling variants).
312
312
let from_fields_at =
313
313
|layout : Self ,
314
314
start : Size |
@@ -354,6 +354,32 @@ impl<'a, Ty> TyLayout<'a, Ty> {
354
354
355
355
let ( mut result, mut total) = from_fields_at ( * self , Size :: ZERO ) ?;
356
356
357
+ match & self . variants {
358
+ abi:: Variants :: Single { .. } => { }
359
+ abi:: Variants :: Multiple { variants, .. } => {
360
+ // Treat enum variants like union members.
361
+ // HACK(eddyb) pretend the `enum` field (discriminant)
362
+ // is at the start of every variant (otherwise the gap
363
+ // at the start of all variants would disqualify them).
364
+ //
365
+ // NB: for all tagged `enum`s (which include all non-C-like
366
+ // `enum`s with defined FFI representation), this will
367
+ // match the homogenous computation on the equivalent
368
+ // `struct { tag; union { variant1; ... } }` and/or
369
+ // `union { struct { tag; variant1; } ... }`
370
+ // (the offsets of variant fields should be identical
371
+ // between the two for either to be a homogenous aggregate).
372
+ let variant_start = total;
373
+ for variant_idx in variants. indices ( ) {
374
+ let ( variant_result, variant_total) =
375
+ from_fields_at ( self . for_variant ( cx, variant_idx) , variant_start) ?;
376
+
377
+ result = result. merge ( variant_result) ?;
378
+ total = total. max ( variant_total) ;
379
+ }
380
+ }
381
+ }
382
+
357
383
// There needs to be no padding.
358
384
if total != self . size {
359
385
Err ( Heterogeneous )
0 commit comments