@@ -8,19 +8,6 @@ use rand_xoshiro::Xoshiro128StarStar;
8
8
9
9
use tracing:: debug;
10
10
11
- // Invert a bijective mapping, i.e. `invert(map)[y] = x` if `map[x] = y`.
12
- // This is used to go between `memory_index` (source field order to memory order)
13
- // and `inverse_memory_index` (memory order to source field order).
14
- // See also `FieldsShape::Arbitrary::memory_index` for more details.
15
- // FIXME(eddyb) build a better abstraction for permutations, if possible.
16
- fn invert_mapping ( map : & [ u32 ] ) -> Vec < u32 > {
17
- let mut inverse = vec ! [ 0 ; map. len( ) ] ;
18
- for i in 0 ..map. len ( ) {
19
- inverse[ map[ i] as usize ] = i as u32 ;
20
- }
21
- inverse
22
- }
23
-
24
11
pub trait LayoutCalculator {
25
12
type TargetDataLayoutRef : Borrow < TargetDataLayout > ;
26
13
@@ -45,8 +32,8 @@ pub trait LayoutCalculator {
45
32
LayoutS {
46
33
variants : Variants :: Single { index : FIRST_VARIANT } ,
47
34
fields : FieldsShape :: Arbitrary {
48
- offsets : vec ! [ Size :: ZERO , b_offset] ,
49
- memory_index : vec ! [ 0 , 1 ] ,
35
+ offsets : [ Size :: ZERO , b_offset] . into ( ) ,
36
+ memory_index : [ 0 , 1 ] . into ( ) ,
50
37
} ,
51
38
abi : Abi :: ScalarPair ( a, b) ,
52
39
largest_niche,
@@ -58,18 +45,18 @@ pub trait LayoutCalculator {
58
45
fn univariant (
59
46
& self ,
60
47
dl : & TargetDataLayout ,
61
- fields : & [ Layout < ' _ > ] ,
48
+ fields : & IndexSlice < FieldIdx , Layout < ' _ > > ,
62
49
repr : & ReprOptions ,
63
50
kind : StructKind ,
64
51
) -> Option < LayoutS > {
65
52
let pack = repr. pack ;
66
53
let mut align = if pack. is_some ( ) { dl. i8_align } else { dl. aggregate_align } ;
67
- let mut inverse_memory_index: Vec < u32 > = ( 0 .. fields. len ( ) as u32 ) . collect ( ) ;
54
+ let mut inverse_memory_index: IndexVec < u32 , FieldIdx > = fields. indices ( ) . collect ( ) ;
68
55
let optimize = !repr. inhibit_struct_field_reordering_opt ( ) ;
69
56
if optimize {
70
57
let end =
71
58
if let StructKind :: MaybeUnsized = kind { fields. len ( ) - 1 } else { fields. len ( ) } ;
72
- let optimizing = & mut inverse_memory_index[ ..end] ;
59
+ let optimizing = & mut inverse_memory_index. raw [ ..end] ;
73
60
let effective_field_align = |layout : Layout < ' _ > | {
74
61
if let Some ( pack) = pack {
75
62
// return the packed alignment in bytes
@@ -105,7 +92,7 @@ pub trait LayoutCalculator {
105
92
// Place ZSTs first to avoid "interesting offsets",
106
93
// especially with only one or two non-ZST fields.
107
94
// Then place largest alignments first, largest niches within an alignment group last
108
- let f = fields[ x as usize ] ;
95
+ let f = fields[ x] ;
109
96
let niche_size = f. largest_niche ( ) . map_or ( 0 , |n| n. available ( dl) ) ;
110
97
( !f. 0 . is_zst ( ) , cmp:: Reverse ( effective_field_align ( f) ) , niche_size)
111
98
} ) ;
@@ -117,7 +104,7 @@ pub trait LayoutCalculator {
117
104
// And put the largest niche in an alignment group at the end
118
105
// so it can be used as discriminant in jagged enums
119
106
optimizing. sort_by_key ( |& x| {
120
- let f = fields[ x as usize ] ;
107
+ let f = fields[ x] ;
121
108
let niche_size = f. largest_niche ( ) . map_or ( 0 , |n| n. available ( dl) ) ;
122
109
( effective_field_align ( f) , niche_size)
123
110
} ) ;
@@ -135,7 +122,7 @@ pub trait LayoutCalculator {
135
122
// At the bottom of this function, we invert `inverse_memory_index` to
136
123
// produce `memory_index` (see `invert_mapping`).
137
124
let mut sized = true ;
138
- let mut offsets = vec ! [ Size :: ZERO ; fields. len ( ) ] ;
125
+ let mut offsets = IndexVec :: from_elem ( Size :: ZERO , & fields) ;
139
126
let mut offset = Size :: ZERO ;
140
127
let mut largest_niche = None ;
141
128
let mut largest_niche_available = 0 ;
@@ -146,7 +133,7 @@ pub trait LayoutCalculator {
146
133
offset = prefix_size. align_to ( prefix_align) ;
147
134
}
148
135
for & i in & inverse_memory_index {
149
- let field = & fields[ i as usize ] ;
136
+ let field = & fields[ i] ;
150
137
if !sized {
151
138
self . delay_bug ( & format ! (
152
139
"univariant: field #{} comes after unsized field" ,
@@ -168,7 +155,7 @@ pub trait LayoutCalculator {
168
155
align = align. max ( field_align) ;
169
156
170
157
debug ! ( "univariant offset: {:?} field: {:#?}" , offset, field) ;
171
- offsets[ i as usize ] = offset;
158
+ offsets[ i] = offset;
172
159
173
160
if let Some ( mut niche) = field. largest_niche ( ) {
174
161
let available = niche. available ( dl) ;
@@ -192,14 +179,18 @@ pub trait LayoutCalculator {
192
179
// If field 5 has offset 0, offsets[0] is 5, and memory_index[5] should be 0.
193
180
// Field 5 would be the first element, so memory_index is i:
194
181
// Note: if we didn't optimize, it's already right.
195
- let memory_index =
196
- if optimize { invert_mapping ( & inverse_memory_index) } else { inverse_memory_index } ;
182
+ let memory_index = if optimize {
183
+ inverse_memory_index. invert_bijective_mapping ( )
184
+ } else {
185
+ debug_assert ! ( inverse_memory_index. iter( ) . copied( ) . eq( fields. indices( ) ) ) ;
186
+ inverse_memory_index. into_iter ( ) . map ( FieldIdx :: as_u32) . collect ( )
187
+ } ;
197
188
let size = min_size. align_to ( align. abi ) ;
198
189
let mut abi = Abi :: Aggregate { sized } ;
199
190
// Unpack newtype ABIs and find scalar pairs.
200
191
if sized && size. bytes ( ) > 0 {
201
192
// All other fields must be ZSTs.
202
- let mut non_zst_fields = fields. iter ( ) . enumerate ( ) . filter ( |& ( _, f) | !f. 0 . is_zst ( ) ) ;
193
+ let mut non_zst_fields = fields. iter_enumerated ( ) . filter ( |& ( _, f) | !f. 0 . is_zst ( ) ) ;
203
194
204
195
match ( non_zst_fields. next ( ) , non_zst_fields. next ( ) , non_zst_fields. next ( ) ) {
205
196
// We have exactly one non-ZST field.
@@ -238,13 +229,13 @@ pub trait LayoutCalculator {
238
229
let pair = self . scalar_pair ( a, b) ;
239
230
let pair_offsets = match pair. fields {
240
231
FieldsShape :: Arbitrary { ref offsets, ref memory_index } => {
241
- assert_eq ! ( memory_index, & [ 0 , 1 ] ) ;
232
+ assert_eq ! ( memory_index. raw , [ 0 , 1 ] ) ;
242
233
offsets
243
234
}
244
235
_ => panic ! ( ) ,
245
236
} ;
246
- if offsets[ i] == pair_offsets[ 0 ]
247
- && offsets[ j] == pair_offsets[ 1 ]
237
+ if offsets[ i] == pair_offsets[ FieldIdx :: from_usize ( 0 ) ]
238
+ && offsets[ j] == pair_offsets[ FieldIdx :: from_usize ( 1 ) ]
248
239
&& align == pair. align
249
240
&& size == pair. size
250
241
{
@@ -289,7 +280,7 @@ pub trait LayoutCalculator {
289
280
fn layout_of_struct_or_enum (
290
281
& self ,
291
282
repr : & ReprOptions ,
292
- variants : & IndexSlice < VariantIdx , Vec < Layout < ' _ > > > ,
283
+ variants : & IndexSlice < VariantIdx , IndexVec < FieldIdx , Layout < ' _ > > > ,
293
284
is_enum : bool ,
294
285
is_unsafe_cell : bool ,
295
286
scalar_valid_range : ( Bound < u128 > , Bound < u128 > ) ,
@@ -312,7 +303,7 @@ pub trait LayoutCalculator {
312
303
// but *not* an encoding of the discriminant (e.g., a tag value).
313
304
// See issue #49298 for more details on the need to leave space
314
305
// for non-ZST uninhabited data (mostly partial initialization).
315
- let absent = |fields : & [ Layout < ' _ > ] | {
306
+ let absent = |fields : & IndexSlice < FieldIdx , Layout < ' _ > > | {
316
307
let uninhabited = fields. iter ( ) . any ( |f| f. abi ( ) . is_uninhabited ( ) ) ;
317
308
let is_zst = fields. iter ( ) . all ( |f| f. 0 . is_zst ( ) ) ;
318
309
uninhabited && is_zst
@@ -510,7 +501,7 @@ pub trait LayoutCalculator {
510
501
// It'll fit, but we need to make some adjustments.
511
502
match layout. fields {
512
503
FieldsShape :: Arbitrary { ref mut offsets, .. } => {
513
- for ( j, offset) in offsets. iter_mut ( ) . enumerate ( ) {
504
+ for ( j, offset) in offsets. iter_enumerated_mut ( ) {
514
505
if !variants[ i] [ j] . 0 . is_zst ( ) {
515
506
* offset += this_offset;
516
507
}
@@ -577,8 +568,8 @@ pub trait LayoutCalculator {
577
568
variants : IndexVec :: new ( ) ,
578
569
} ,
579
570
fields : FieldsShape :: Arbitrary {
580
- offsets : vec ! [ niche_offset] ,
581
- memory_index : vec ! [ 0 ] ,
571
+ offsets : [ niche_offset] . into ( ) ,
572
+ memory_index : [ 0 ] . into ( ) ,
582
573
} ,
583
574
abi,
584
575
largest_niche,
@@ -651,7 +642,8 @@ pub trait LayoutCalculator {
651
642
st. variants = Variants :: Single { index : i } ;
652
643
// Find the first field we can't move later
653
644
// to make room for a larger discriminant.
654
- for field in st. fields . index_by_increasing_offset ( ) . map ( |j| & field_layouts[ j] ) {
645
+ for field_idx in st. fields . index_by_increasing_offset ( ) {
646
+ let field = & field_layouts[ FieldIdx :: from_usize ( field_idx) ] ;
655
647
if !field. 0 . is_zst ( ) || field. align ( ) . abi . bytes ( ) != 1 {
656
648
start_align = start_align. min ( field. align ( ) . abi ) ;
657
649
break ;
@@ -802,13 +794,13 @@ pub trait LayoutCalculator {
802
794
let pair = self . scalar_pair ( tag, prim_scalar) ;
803
795
let pair_offsets = match pair. fields {
804
796
FieldsShape :: Arbitrary { ref offsets, ref memory_index } => {
805
- assert_eq ! ( memory_index, & [ 0 , 1 ] ) ;
797
+ assert_eq ! ( memory_index. raw , [ 0 , 1 ] ) ;
806
798
offsets
807
799
}
808
800
_ => panic ! ( ) ,
809
801
} ;
810
- if pair_offsets[ 0 ] == Size :: ZERO
811
- && pair_offsets[ 1 ] == * offset
802
+ if pair_offsets[ FieldIdx :: from_u32 ( 0 ) ] == Size :: ZERO
803
+ && pair_offsets[ FieldIdx :: from_u32 ( 1 ) ] == * offset
812
804
&& align == pair. align
813
805
&& size == pair. size
814
806
{
@@ -844,7 +836,10 @@ pub trait LayoutCalculator {
844
836
tag_field : 0 ,
845
837
variants : IndexVec :: new ( ) ,
846
838
} ,
847
- fields : FieldsShape :: Arbitrary { offsets : vec ! [ Size :: ZERO ] , memory_index : vec ! [ 0 ] } ,
839
+ fields : FieldsShape :: Arbitrary {
840
+ offsets : [ Size :: ZERO ] . into ( ) ,
841
+ memory_index : [ 0 ] . into ( ) ,
842
+ } ,
848
843
largest_niche,
849
844
abi,
850
845
align,
@@ -883,7 +878,7 @@ pub trait LayoutCalculator {
883
878
fn layout_of_union (
884
879
& self ,
885
880
repr : & ReprOptions ,
886
- variants : & IndexSlice < VariantIdx , Vec < Layout < ' _ > > > ,
881
+ variants : & IndexSlice < VariantIdx , IndexVec < FieldIdx , Layout < ' _ > > > ,
887
882
) -> Option < LayoutS > {
888
883
let dl = self . current_data_layout ( ) ;
889
884
let dl = dl. borrow ( ) ;
0 commit comments