@@ -248,16 +248,36 @@ fn sanity_check_layout<'tcx>(
248248 "size mismatch between ABI and layout in {layout:#?}"
249249 );*/
250250 }
251+ Abi :: Vector { count, element } => {
252+ // No padding in vectors. Alignment can be strengthened, though.
253+ assert ! (
254+ layout. align( ) . abi >= element. align( & tcx) . abi,
255+ "alignment mismatch between ABI and layout in {layout:#?}"
256+ ) ;
257+ let size = element. size ( & tcx) * count;
258+ assert_eq ! (
259+ layout. size( ) ,
260+ size. align_to( tcx. data_layout( ) . vector_align( size) . abi) ,
261+ "size mismatch between ABI and layout in {layout:#?}"
262+ ) ;
263+ }
251264 Abi :: ScalarPair ( scalar1, scalar2) => {
252- // Sanity-check scalar pair size.
253- let field2_offset = scalar1. size ( & tcx) . align_to ( scalar2. align ( & tcx) . abi ) ;
254- let total = field2_offset + scalar2. size ( & tcx) ;
265+ // Sanity-check scalar pairs. These are a bit more flexible and support
266+ // padding, but we can at least ensure both fields actually fit into the layout
267+ // and the alignment requirement has not been weakened.
268+ let align1 = scalar1. align ( & tcx) . abi ;
269+ let align2 = scalar2. align ( & tcx) . abi ;
255270 assert ! (
256- layout. size( ) >= total,
271+ layout. align( ) . abi >= cmp:: max( align1, align2) ,
272+ "alignment mismatch between ABI and layout in {layout:#?}" ,
273+ ) ;
274+ let field2_offset = scalar1. size ( & tcx) . align_to ( align2) ;
275+ assert ! (
276+ layout. size( ) >= field2_offset + scalar2. size( & tcx) ,
257277 "size mismatch between ABI and layout in {layout:#?}"
258278 ) ;
259279 }
260- _ => { }
280+ Abi :: Uninhabited | Abi :: Aggregate { .. } => { } // Nothing to check.
261281 }
262282 }
263283
@@ -1401,16 +1421,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
14011421 // Without latter check aligned enums with custom discriminant values
14021422 // Would result in ICE see the issue #92464 for more info
14031423 abi = Abi :: Scalar ( tag) ;
1404- // Make sure the variants with fields have the same ABI as the enum itself
1405- // (since downcasting to them is a NOP).
1406- for variant in & mut layout_variants {
1407- if variant. fields . count ( ) > 0
1408- && matches ! ( variant. abi, Abi :: Aggregate { .. } )
1409- {
1410- assert_eq ! ( variant. size, size) ;
1411- variant. abi = abi;
1412- }
1413- }
14141424 } else {
14151425 // Try to use a ScalarPair for all tagged enums.
14161426 let mut common_prim = None ;
@@ -1479,17 +1489,24 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
14791489 // We can use `ScalarPair` only when it matches our
14801490 // already computed layout (including `#[repr(C)]`).
14811491 abi = pair. abi ;
1482- // Make sure the variants with fields have the same ABI as the enum itself
1483- // (since downcasting to them is a NOP).
1484- for variant in & mut layout_variants {
1485- if variant. fields . count ( ) > 0
1486- && matches ! ( variant. abi, Abi :: Aggregate { .. } )
1487- {
1488- variant. abi = abi;
1489- // Also need to bump up the size, so that the pair fits inside.
1490- variant. size = size;
1491- }
1492- }
1492+ }
1493+ }
1494+ }
1495+
1496+ // If we pick a "clever" (by-value) ABI, we might have to adjust the ABI of the
1497+ // variants to ensure they are consistent. This is because a downcast is
1498+ // semantically a NOP, and thus should not affect layout.
1499+ if matches ! ( abi, Abi :: Scalar ( ..) | Abi :: ScalarPair ( ..) ) {
1500+ for variant in & mut layout_variants {
1501+ // We only do this for variants with fields; the others are not accessed anyway.
1502+ // Also do not overwrite any already existing "clever" ABIs.
1503+ if variant. fields . count ( ) > 0
1504+ && matches ! ( variant. abi, Abi :: Aggregate { .. } )
1505+ {
1506+ variant. abi = abi;
1507+ // Also need to bump up the size and alignment, so that the entire value fits in here.
1508+ variant. size = cmp:: max ( variant. size , size) ;
1509+ variant. align . abi = cmp:: max ( variant. align . abi , align. abi ) ;
14931510 }
14941511 }
14951512 }
0 commit comments