@@ -308,7 +308,7 @@ impl<'a, Ty> TyLayout<'a, Ty> {
308308
309309 Abi :: ScalarPair ( ..) | Abi :: Aggregate { .. } => {
310310 // 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).
312312 let from_fields_at =
313313 |layout : Self ,
314314 start : Size |
@@ -354,6 +354,32 @@ impl<'a, Ty> TyLayout<'a, Ty> {
354354
355355 let ( mut result, mut total) = from_fields_at ( * self , Size :: ZERO ) ?;
356356
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+
357383 // There needs to be no padding.
358384 if total != self . size {
359385 Err ( Heterogeneous )
0 commit comments