@@ -4,7 +4,7 @@ use rustc_middle::ty::{
44} ;
55use rustc_target:: abi:: * ;
66
7- use std:: cmp ;
7+ use std:: assert_matches :: assert_matches ;
88
99/// Enforce some basic invariants on layouts.
1010pub ( super ) fn sanity_check_layout < ' tcx > (
@@ -68,21 +68,31 @@ pub(super) fn sanity_check_layout<'tcx>(
6868 }
6969
7070 fn check_layout_abi < ' tcx > ( cx : & LayoutCx < ' tcx , TyCtxt < ' tcx > > , layout : & TyAndLayout < ' tcx > ) {
71+ // Verify the ABI mandated alignment and size.
72+ let align = layout. abi . inherent_align ( cx) . map ( |align| align. abi ) ;
73+ let size = layout. abi . inherent_size ( cx) ;
74+ let Some ( ( align, size) ) = align. zip ( size) else {
75+ assert_matches ! (
76+ layout. layout. abi( ) ,
77+ Abi :: Uninhabited | Abi :: Aggregate { .. } ,
78+ "ABI unexpectedly missing alignment and/or size in {layout:#?}"
79+ ) ;
80+ return
81+ } ;
82+ assert_eq ! (
83+ layout. layout. align( ) . abi,
84+ align,
85+ "alignment mismatch between ABI and layout in {layout:#?}"
86+ ) ;
87+ assert_eq ! (
88+ layout. layout. size( ) ,
89+ size,
90+ "size mismatch between ABI and layout in {layout:#?}"
91+ ) ;
92+
93+ // Verify per-ABI invariants
7194 match layout. layout . abi ( ) {
72- Abi :: Scalar ( scalar) => {
73- // No padding in scalars.
74- let size = scalar. size ( cx) ;
75- let align = scalar. align ( cx) . abi ;
76- assert_eq ! (
77- layout. layout. size( ) ,
78- size,
79- "size mismatch between ABI and layout in {layout:#?}"
80- ) ;
81- assert_eq ! (
82- layout. layout. align( ) . abi,
83- align,
84- "alignment mismatch between ABI and layout in {layout:#?}"
85- ) ;
95+ Abi :: Scalar ( _) => {
8696 // Check that this matches the underlying field.
8797 let inner = skip_newtypes ( cx, layout) ;
8898 assert ! (
@@ -135,24 +145,6 @@ pub(super) fn sanity_check_layout<'tcx>(
135145 }
136146 }
137147 Abi :: ScalarPair ( scalar1, scalar2) => {
138- // Sanity-check scalar pairs. Computing the expected size and alignment is a bit of work.
139- let size1 = scalar1. size ( cx) ;
140- let align1 = scalar1. align ( cx) . abi ;
141- let size2 = scalar2. size ( cx) ;
142- let align2 = scalar2. align ( cx) . abi ;
143- let align = cmp:: max ( align1, align2) ;
144- let field2_offset = size1. align_to ( align2) ;
145- let size = ( field2_offset + size2) . align_to ( align) ;
146- assert_eq ! (
147- layout. layout. size( ) ,
148- size,
149- "size mismatch between ABI and layout in {layout:#?}"
150- ) ;
151- assert_eq ! (
152- layout. layout. align( ) . abi,
153- align,
154- "alignment mismatch between ABI and layout in {layout:#?}" ,
155- ) ;
156148 // Check that the underlying pair of fields matches.
157149 let inner = skip_newtypes ( cx, layout) ;
158150 assert ! (
@@ -189,8 +181,9 @@ pub(super) fn sanity_check_layout<'tcx>(
189181 "`ScalarPair` layout for type with less than two non-ZST fields: {inner:#?}"
190182 )
191183 } ) ;
192- assert ! (
193- fields. next( ) . is_none( ) ,
184+ assert_matches ! (
185+ fields. next( ) ,
186+ None ,
194187 "`ScalarPair` layout for type with at least three non-ZST fields: {inner:#?}"
195188 ) ;
196189 // The fields might be in opposite order.
@@ -200,6 +193,10 @@ pub(super) fn sanity_check_layout<'tcx>(
200193 ( offset2, field2, offset1, field1)
201194 } ;
202195 // The fields should be at the right offset, and match the `scalar` layout.
196+ let size1 = scalar1. size ( cx) ;
197+ let align1 = scalar1. align ( cx) . abi ;
198+ let size2 = scalar2. size ( cx) ;
199+ let align2 = scalar2. align ( cx) . abi ;
203200 assert_eq ! (
204201 offset1,
205202 Size :: ZERO ,
@@ -213,10 +210,12 @@ pub(super) fn sanity_check_layout<'tcx>(
213210 field1. align. abi, align1,
214211 "`ScalarPair` first field with bad align in {inner:#?}" ,
215212 ) ;
216- assert ! (
217- matches!( field1. abi, Abi :: Scalar ( _) ) ,
213+ assert_matches ! (
214+ field1. abi,
215+ Abi :: Scalar ( _) ,
218216 "`ScalarPair` first field with bad ABI in {inner:#?}" ,
219217 ) ;
218+ let field2_offset = size1. align_to ( align2) ;
220219 assert_eq ! (
221220 offset2, field2_offset,
222221 "`ScalarPair` second field at bad offset in {inner:#?}" ,
@@ -229,27 +228,14 @@ pub(super) fn sanity_check_layout<'tcx>(
229228 field2. align. abi, align2,
230229 "`ScalarPair` second field with bad align in {inner:#?}" ,
231230 ) ;
232- assert ! (
233- matches!( field2. abi, Abi :: Scalar ( _) ) ,
231+ assert_matches ! (
232+ field2. abi,
233+ Abi :: Scalar ( _) ,
234234 "`ScalarPair` second field with bad ABI in {inner:#?}" ,
235235 ) ;
236236 }
237- Abi :: Vector { count, element } => {
238- // No padding in vectors, except possibly for trailing padding to make the size a multiple of align.
239- let size = element. size ( cx) * count;
240- let align = cx. data_layout ( ) . vector_align ( size) . abi ;
241- let size = size. align_to ( align) ; // needed e.g. for vectors of size 3
237+ Abi :: Vector { element, .. } => {
242238 assert ! ( align >= element. align( cx) . abi) ; // just sanity-checking `vector_align`.
243- assert_eq ! (
244- layout. layout. size( ) ,
245- size,
246- "size mismatch between ABI and layout in {layout:#?}"
247- ) ;
248- assert_eq ! (
249- layout. layout. align( ) . abi,
250- align,
251- "alignment mismatch between ABI and layout in {layout:#?}"
252- ) ;
253239 // FIXME: Do some kind of check of the inner type, like for Scalar and ScalarPair.
254240 }
255241 Abi :: Uninhabited | Abi :: Aggregate { .. } => { } // Nothing to check.
0 commit comments