@@ -36,12 +36,14 @@ enum NicheBias {
36
36
}
37
37
38
38
#[ derive( Copy , Clone , Debug ) ]
39
- pub enum LayoutCalculatorError {
39
+ pub enum LayoutCalculatorError < F > {
40
40
/// An unsized type was found in a location where a sized type was expected.
41
41
///
42
42
/// This is not always a compile error, for example if there is a `[T]: Sized`
43
43
/// bound in a where clause.
44
- UnexpectedUnsized ,
44
+ ///
45
+ /// Contains the field that was unexpectedly unsized.
46
+ UnexpectedUnsized ( F ) ,
45
47
46
48
/// A type was too large for the target platform.
47
49
SizeOverflow ,
@@ -50,8 +52,8 @@ pub enum LayoutCalculatorError {
50
52
EmptyUnion ,
51
53
}
52
54
53
- type LayoutCalculatorResult < FieldIdx , VariantIdx > =
54
- Result < LayoutS < FieldIdx , VariantIdx > , LayoutCalculatorError > ;
55
+ type LayoutCalculatorResult < FieldIdx , VariantIdx , F > =
56
+ Result < LayoutS < FieldIdx , VariantIdx > , LayoutCalculatorError < F > > ;
55
57
56
58
#[ derive( Clone , Copy , Debug ) ]
57
59
pub struct LayoutCalculator < Cx > {
@@ -100,13 +102,13 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
100
102
' a ,
101
103
FieldIdx : Idx ,
102
104
VariantIdx : Idx ,
103
- F : Deref < Target = & ' a LayoutS < FieldIdx , VariantIdx > > + fmt:: Debug ,
105
+ F : Deref < Target = & ' a LayoutS < FieldIdx , VariantIdx > > + fmt:: Debug + Copy ,
104
106
> (
105
107
& self ,
106
108
fields : & IndexSlice < FieldIdx , F > ,
107
109
repr : & ReprOptions ,
108
110
kind : StructKind ,
109
- ) -> LayoutCalculatorResult < FieldIdx , VariantIdx > {
111
+ ) -> LayoutCalculatorResult < FieldIdx , VariantIdx , F > {
110
112
let dl = self . cx . data_layout ( ) ;
111
113
let layout = self . univariant_biased ( fields, repr, kind, NicheBias :: Start ) ;
112
114
// Enums prefer niches close to the beginning or the end of the variants so that other
@@ -191,7 +193,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
191
193
' a ,
192
194
FieldIdx : Idx ,
193
195
VariantIdx : Idx ,
194
- F : Deref < Target = & ' a LayoutS < FieldIdx , VariantIdx > > + fmt:: Debug ,
196
+ F : Deref < Target = & ' a LayoutS < FieldIdx , VariantIdx > > + fmt:: Debug + Copy ,
195
197
> (
196
198
& self ,
197
199
repr : & ReprOptions ,
@@ -203,7 +205,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
203
205
discriminants : impl Iterator < Item = ( VariantIdx , i128 ) > ,
204
206
dont_niche_optimize_enum : bool ,
205
207
always_sized : bool ,
206
- ) -> LayoutCalculatorResult < FieldIdx , VariantIdx > {
208
+ ) -> LayoutCalculatorResult < FieldIdx , VariantIdx , F > {
207
209
let ( present_first, present_second) = {
208
210
let mut present_variants = variants
209
211
. iter_enumerated ( )
@@ -254,12 +256,12 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
254
256
' a ,
255
257
FieldIdx : Idx ,
256
258
VariantIdx : Idx ,
257
- F : Deref < Target = & ' a LayoutS < FieldIdx , VariantIdx > > + fmt:: Debug ,
259
+ F : Deref < Target = & ' a LayoutS < FieldIdx , VariantIdx > > + fmt:: Debug + Copy ,
258
260
> (
259
261
& self ,
260
262
repr : & ReprOptions ,
261
263
variants : & IndexSlice < VariantIdx , IndexVec < FieldIdx , F > > ,
262
- ) -> LayoutCalculatorResult < FieldIdx , VariantIdx > {
264
+ ) -> LayoutCalculatorResult < FieldIdx , VariantIdx , F > {
263
265
let dl = self . cx . data_layout ( ) ;
264
266
let mut align = if repr. pack . is_some ( ) { dl. i8_align } else { dl. aggregate_align } ;
265
267
let mut max_repr_align = repr. align ;
@@ -279,7 +281,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
279
281
let only_variant = & variants[ only_variant_idx] ;
280
282
for field in only_variant {
281
283
if field. is_unsized ( ) {
282
- return Err ( LayoutCalculatorError :: UnexpectedUnsized ) ;
284
+ return Err ( LayoutCalculatorError :: UnexpectedUnsized ( * field ) ) ;
283
285
}
284
286
285
287
align = align. max ( field. align ) ;
@@ -359,7 +361,12 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
359
361
}
360
362
361
363
/// single-variant enums are just structs, if you think about it
362
- fn layout_of_struct < ' a , FieldIdx : Idx , VariantIdx : Idx , F > (
364
+ fn layout_of_struct <
365
+ ' a ,
366
+ FieldIdx : Idx ,
367
+ VariantIdx : Idx ,
368
+ F : Deref < Target = & ' a LayoutS < FieldIdx , VariantIdx > > + fmt:: Debug + Copy ,
369
+ > (
363
370
& self ,
364
371
repr : & ReprOptions ,
365
372
variants : & IndexSlice < VariantIdx , IndexVec < FieldIdx , F > > ,
@@ -368,10 +375,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
368
375
scalar_valid_range : ( Bound < u128 > , Bound < u128 > ) ,
369
376
always_sized : bool ,
370
377
present_first : VariantIdx ,
371
- ) -> LayoutCalculatorResult < FieldIdx , VariantIdx >
372
- where
373
- F : Deref < Target = & ' a LayoutS < FieldIdx , VariantIdx > > + fmt:: Debug ,
374
- {
378
+ ) -> LayoutCalculatorResult < FieldIdx , VariantIdx , F > {
375
379
// Struct, or univariant enum equivalent to a struct.
376
380
// (Typechecking will reject discriminant-sizing attrs.)
377
381
@@ -457,17 +461,19 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
457
461
Ok ( st)
458
462
}
459
463
460
- fn layout_of_enum < ' a , FieldIdx : Idx , VariantIdx : Idx , F > (
464
+ fn layout_of_enum <
465
+ ' a ,
466
+ FieldIdx : Idx ,
467
+ VariantIdx : Idx ,
468
+ F : Deref < Target = & ' a LayoutS < FieldIdx , VariantIdx > > + fmt:: Debug + Copy ,
469
+ > (
461
470
& self ,
462
471
repr : & ReprOptions ,
463
472
variants : & IndexSlice < VariantIdx , IndexVec < FieldIdx , F > > ,
464
473
discr_range_of_repr : impl Fn ( i128 , i128 ) -> ( Integer , bool ) ,
465
474
discriminants : impl Iterator < Item = ( VariantIdx , i128 ) > ,
466
475
dont_niche_optimize_enum : bool ,
467
- ) -> LayoutCalculatorResult < FieldIdx , VariantIdx >
468
- where
469
- F : Deref < Target = & ' a LayoutS < FieldIdx , VariantIdx > > + fmt:: Debug ,
470
- {
476
+ ) -> LayoutCalculatorResult < FieldIdx , VariantIdx , F > {
471
477
// Until we've decided whether to use the tagged or
472
478
// niche filling LayoutS, we don't want to intern the
473
479
// variant layouts, so we can't store them in the
@@ -972,14 +978,14 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
972
978
' a ,
973
979
FieldIdx : Idx ,
974
980
VariantIdx : Idx ,
975
- F : Deref < Target = & ' a LayoutS < FieldIdx , VariantIdx > > + fmt:: Debug ,
981
+ F : Deref < Target = & ' a LayoutS < FieldIdx , VariantIdx > > + fmt:: Debug + Copy ,
976
982
> (
977
983
& self ,
978
984
fields : & IndexSlice < FieldIdx , F > ,
979
985
repr : & ReprOptions ,
980
986
kind : StructKind ,
981
987
niche_bias : NicheBias ,
982
- ) -> LayoutCalculatorResult < FieldIdx , VariantIdx > {
988
+ ) -> LayoutCalculatorResult < FieldIdx , VariantIdx , F > {
983
989
let dl = self . cx . data_layout ( ) ;
984
990
let pack = repr. pack ;
985
991
let mut align = if pack. is_some ( ) { dl. i8_align } else { dl. aggregate_align } ;
@@ -1124,7 +1130,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
1124
1130
// field 5 with offset 0 puts 0 in offsets[5].
1125
1131
// At the bottom of this function, we invert `inverse_memory_index` to
1126
1132
// produce `memory_index` (see `invert_mapping`).
1127
- let mut sized = true ;
1133
+ let mut unsized_field = None :: < & F > ;
1128
1134
let mut offsets = IndexVec :: from_elem ( Size :: ZERO , fields) ;
1129
1135
let mut offset = Size :: ZERO ;
1130
1136
let mut largest_niche = None ;
@@ -1137,12 +1143,12 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
1137
1143
}
1138
1144
for & i in & inverse_memory_index {
1139
1145
let field = & fields[ i] ;
1140
- if !sized {
1141
- return Err ( LayoutCalculatorError :: UnexpectedUnsized ) ;
1146
+ if let Some ( unsized_field ) = unsized_field {
1147
+ return Err ( LayoutCalculatorError :: UnexpectedUnsized ( * unsized_field ) ) ;
1142
1148
}
1143
1149
1144
1150
if field. is_unsized ( ) {
1145
- sized = false ;
1151
+ unsized_field = Some ( field ) ;
1146
1152
}
1147
1153
1148
1154
// Invariant: offset < dl.obj_size_bound() <= 1<<61
@@ -1206,6 +1212,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
1206
1212
return Err ( LayoutCalculatorError :: SizeOverflow ) ;
1207
1213
}
1208
1214
let mut layout_of_single_non_zst_field = None ;
1215
+ let sized = unsized_field. is_none ( ) ;
1209
1216
let mut abi = Abi :: Aggregate { sized } ;
1210
1217
1211
1218
let optimize_abi = !repr. inhibit_newtype_abi_optimization ( ) ;
0 commit comments