1
1
use std:: assert_matches:: assert_matches;
2
2
3
+ use rustc_abi:: LayoutCalculatorError ;
3
4
use rustc_middle:: bug;
4
5
use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutCx , TyAndLayout } ;
5
6
use rustc_target:: abi:: * ;
6
7
7
8
/// Enforce some basic invariants on layouts.
8
- pub ( super ) fn partially_check_layout < ' tcx > ( cx : & LayoutCx < ' tcx > , layout : & TyAndLayout < ' tcx > ) {
9
+ ///
10
+ /// Note most of the code is skipped if debug assertions are not enabled,
11
+ /// and we bail left and right, thus the name of "partially check".
12
+ pub ( super ) fn partially_check_layout < ' tcx > (
13
+ cx : & LayoutCx < ' tcx > ,
14
+ layout : & TyAndLayout < ' tcx > ,
15
+ ) -> Result < ( ) , LayoutCalculatorError < TyAndLayout < ' tcx > > > {
9
16
let tcx = cx. tcx ( ) ;
10
17
11
18
// Type-level uninhabitedness should always imply ABI uninhabitedness.
@@ -22,7 +29,7 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa
22
29
23
30
if !cfg ! ( debug_assertions) {
24
31
// Stop here, the rest is kind of expensive.
25
- return ;
32
+ return Ok ( ( ) ) ;
26
33
}
27
34
28
35
/// Yields non-ZST fields of the type
@@ -64,7 +71,10 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa
64
71
* layout
65
72
}
66
73
67
- fn check_layout_abi < ' tcx > ( cx : & LayoutCx < ' tcx > , layout : & TyAndLayout < ' tcx > ) {
74
+ fn check_layout_abi < ' tcx > (
75
+ cx : & LayoutCx < ' tcx > ,
76
+ layout : & TyAndLayout < ' tcx > ,
77
+ ) -> Result < ( ) , LayoutCalculatorError < TyAndLayout < ' tcx > > > {
68
78
// Verify the ABI mandated alignment and size.
69
79
let align = layout. abi . inherent_align ( cx) . map ( |align| align. abi ) ;
70
80
let size = layout. abi . inherent_size ( cx) ;
@@ -74,21 +84,19 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa
74
84
Abi :: Uninhabited | Abi :: Aggregate { .. } ,
75
85
"ABI unexpectedly missing alignment and/or size in {layout:#?}"
76
86
) ;
77
- return ;
87
+ return Ok ( ( ) ) ;
78
88
} ;
79
- assert_eq ! (
80
- layout. layout. align( ) . abi,
81
- align,
82
- "alignment mismatch between ABI and layout in {layout:#?}"
83
- ) ;
89
+ if layout. layout . align ( ) . abi != align {
90
+ return Err ( LayoutCalculatorError :: ReprConflict ) ;
91
+ }
84
92
assert_eq ! (
85
93
layout. layout. size( ) ,
86
94
size,
87
95
"size mismatch between ABI and layout in {layout:#?}"
88
96
) ;
89
97
90
98
// Verify per-ABI invariants
91
- match layout. layout . abi ( ) {
99
+ let _unit = match layout. layout . abi ( ) {
92
100
Abi :: Scalar ( _) => {
93
101
// Check that this matches the underlying field.
94
102
let inner = skip_newtypes ( cx, layout) ;
@@ -104,7 +112,7 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa
104
112
}
105
113
FieldsShape :: Union ( ..) => {
106
114
// FIXME: I guess we could also check something here? Like, look at all fields?
107
- return ;
115
+ return Ok ( ( ) ) ;
108
116
}
109
117
FieldsShape :: Arbitrary { .. } => {
110
118
// Should be an enum, the only field is the discriminant.
@@ -153,15 +161,15 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa
153
161
if matches ! ( inner. layout. variants( ) , Variants :: Multiple { .. } ) {
154
162
// FIXME: ScalarPair for enums is enormously complicated and it is very hard
155
163
// to check anything about them.
156
- return ;
164
+ return Ok ( ( ) ) ;
157
165
}
158
166
match inner. layout . fields ( ) {
159
167
FieldsShape :: Arbitrary { .. } => {
160
168
// Checked below.
161
169
}
162
170
FieldsShape :: Union ( ..) => {
163
171
// FIXME: I guess we could also check something here? Like, look at all fields?
164
- return ;
172
+ return Ok ( ( ) ) ;
165
173
}
166
174
_ => {
167
175
panic ! ( "`ScalarPair` layout with unexpected field shape in {inner:#?}" ) ;
@@ -236,10 +244,11 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa
236
244
// FIXME: Do some kind of check of the inner type, like for Scalar and ScalarPair.
237
245
}
238
246
Abi :: Uninhabited | Abi :: Aggregate { .. } => { } // Nothing to check.
239
- }
247
+ } ;
248
+ Ok ( _unit)
240
249
}
241
250
242
- check_layout_abi ( cx, layout) ;
251
+ let _unit = check_layout_abi ( cx, layout) ? ;
243
252
244
253
if let Variants :: Multiple { variants, .. } = & layout. variants {
245
254
for variant in variants. iter ( ) {
@@ -293,4 +302,5 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa
293
302
}
294
303
}
295
304
}
305
+ Ok ( ( ) )
296
306
}
0 commit comments