@@ -240,7 +240,11 @@ fn sanity_check_layout<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, layout: &TyAndLa
240
240
) -> impl Iterator < Item = ( Size , TyAndLayout < ' tcx > ) > + ' a {
241
241
( 0 ..layout. layout . fields ( ) . count ( ) ) . filter_map ( |i| {
242
242
let field = layout. field ( cx, i) ;
243
- let zst = field. is_zst ( ) && field. align . abi . bytes ( ) == 1 ;
243
+ // Also checking `align == 1` here leads to test failures in
244
+ // `layout/zero-sized-array-union.rs`, where a type has a zero-size field with
245
+ // alignment 4 that still gets ignored during layout computation (which is okay
246
+ // since other fields already force alignment 4).
247
+ let zst = field. is_zst ( ) ;
244
248
( !zst) . then ( || ( layout. fields . offset ( i) , field) )
245
249
} )
246
250
}
@@ -327,38 +331,120 @@ fn sanity_check_layout<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, layout: &TyAndLa
327
331
field. align. abi, align,
328
332
"`Scalar` field with bad align in {inner:#?}" ,
329
333
) ;
334
+ assert ! (
335
+ matches!( field. abi, Abi :: Scalar ( _) ) ,
336
+ "`Scalar` field with bad ABI in {inner:#?}" ,
337
+ ) ;
330
338
}
331
339
_ => {
332
340
panic ! ( "`Scalar` layout for non-primitive non-enum type {}" , inner. ty) ;
333
341
}
334
342
}
335
343
}
336
- Abi :: Vector { count, element } => {
337
- // No padding in vectors. Alignment can be strengthened, though.
338
- assert ! (
339
- layout. layout. align( ) . abi >= element. align( cx) . abi,
340
- "alignment mismatch between ABI and layout in {layout:#?}"
341
- ) ;
342
- let size = element. size ( cx) * count;
343
- assert_eq ! (
344
- layout. layout. size( ) ,
345
- size. align_to( cx. data_layout( ) . vector_align( size) . abi) ,
346
- "size mismatch between ABI and layout in {layout:#?}"
347
- ) ;
348
- }
349
344
Abi :: ScalarPair ( scalar1, scalar2) => {
350
345
// Sanity-check scalar pairs. These are a bit more flexible and support
351
346
// padding, but we can at least ensure both fields actually fit into the layout
352
347
// and the alignment requirement has not been weakened.
348
+ let size1 = scalar1. size ( cx) ;
353
349
let align1 = scalar1. align ( cx) . abi ;
350
+ let size2 = scalar2. size ( cx) ;
354
351
let align2 = scalar2. align ( cx) . abi ;
355
352
assert ! (
356
353
layout. layout. align( ) . abi >= cmp:: max( align1, align2) ,
357
354
"alignment mismatch between ABI and layout in {layout:#?}" ,
358
355
) ;
359
- let field2_offset = scalar1. size ( cx) . align_to ( align2) ;
356
+ let field2_offset = size1. align_to ( align2) ;
357
+ assert ! (
358
+ layout. layout. size( ) >= field2_offset + size2,
359
+ "size mismatch between ABI and layout in {layout:#?}"
360
+ ) ;
361
+ // Check that the underlying pair of fields matches.
362
+ let inner = skip_newtypes ( cx, layout) ;
363
+ assert ! (
364
+ matches!( inner. layout. abi( ) , Abi :: ScalarPair ( ..) ) ,
365
+ "`ScalarPair` type {} is newtype around non-`ScalarPair` type {}" ,
366
+ layout. ty,
367
+ inner. ty
368
+ ) ;
369
+ if matches ! ( inner. layout. variants( ) , Variants :: Multiple { .. } ) {
370
+ // FIXME: ScalarPair for enums is enormously complicated and it is very hard
371
+ // to check anything about them.
372
+ return ;
373
+ }
374
+ match inner. layout . fields ( ) {
375
+ FieldsShape :: Arbitrary { .. } => {
376
+ // Checked below.
377
+ }
378
+ FieldsShape :: Union ( ..) => {
379
+ // FIXME: I guess we could also check something here? Like, look at all fields?
380
+ return ;
381
+ }
382
+ _ => {
383
+ panic ! ( "`ScalarPair` layout with unexpected field shape in {inner:#?}" ) ;
384
+ }
385
+ }
386
+ let mut fields = non_zst_fields ( cx, & inner) ;
387
+ let ( offset1, field1) = fields. next ( ) . unwrap_or_else ( || {
388
+ panic ! ( "`ScalarPair` layout for type with not even one non-ZST field: {inner:#?}" )
389
+ } ) ;
390
+ let ( offset2, field2) = fields. next ( ) . unwrap_or_else ( || {
391
+ panic ! ( "`ScalarPair` layout for type with less than two non-ZST fields: {inner:#?}" )
392
+ } ) ;
393
+ assert ! (
394
+ fields. next( ) . is_none( ) ,
395
+ "`ScalarPair` layout for type with at least three non-ZST fields: {inner:#?}"
396
+ ) ;
397
+ // The fields might be in opposite order.
398
+ let ( offset1, field1, offset2, field2) = if offset1 <= offset2 {
399
+ ( offset1, field1, offset2, field2)
400
+ } else {
401
+ ( offset2, field2, offset1, field1)
402
+ } ;
403
+ // The fields should be at the right offset, and match the `scalar` layout.
404
+ assert_eq ! (
405
+ offset1,
406
+ Size :: ZERO ,
407
+ "`ScalarPair` first field at non-0 offset in {inner:#?}" ,
408
+ ) ;
409
+ assert_eq ! (
410
+ field1. size, size1,
411
+ "`ScalarPair` first field with bad size in {inner:#?}" ,
412
+ ) ;
413
+ assert_eq ! (
414
+ field1. align. abi, align1,
415
+ "`ScalarPair` first field with bad align in {inner:#?}" ,
416
+ ) ;
417
+ assert ! (
418
+ matches!( field1. abi, Abi :: Scalar ( _) ) ,
419
+ "`ScalarPair` first field with bad ABI in {inner:#?}" ,
420
+ ) ;
421
+ assert_eq ! (
422
+ offset2, field2_offset,
423
+ "`ScalarPair` second field at bad offset in {inner:#?}" ,
424
+ ) ;
425
+ assert_eq ! (
426
+ field2. size, size2,
427
+ "`ScalarPair` second field with bad size in {inner:#?}" ,
428
+ ) ;
429
+ assert_eq ! (
430
+ field2. align. abi, align2,
431
+ "`ScalarPair` second field with bad align in {inner:#?}" ,
432
+ ) ;
433
+ assert ! (
434
+ matches!( field2. abi, Abi :: Scalar ( _) ) ,
435
+ "`ScalarPair` second field with bad ABI in {inner:#?}" ,
436
+ ) ;
437
+ }
438
+ Abi :: Vector { count, element } => {
439
+ // No padding in vectors. Alignment can be strengthened, though.
360
440
assert ! (
361
- layout. layout. size( ) >= field2_offset + scalar2. size( cx) ,
441
+ layout. layout. align( ) . abi >= element. align( cx) . abi,
442
+ "alignment mismatch between ABI and layout in {layout:#?}"
443
+ ) ;
444
+ let size = element. size ( cx) * count;
445
+ assert_eq ! (
446
+ layout. layout. size( ) ,
447
+ size. align_to( cx. data_layout( ) . vector_align( size) . abi) ,
362
448
"size mismatch between ABI and layout in {layout:#?}"
363
449
) ;
364
450
}
0 commit comments