@@ -8,19 +8,6 @@ use rand_xoshiro::Xoshiro128StarStar;
88
99use tracing:: debug;
1010
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-
2411pub trait LayoutCalculator {
2512 type TargetDataLayoutRef : Borrow < TargetDataLayout > ;
2613
@@ -45,8 +32,8 @@ pub trait LayoutCalculator {
4532 LayoutS {
4633 variants : Variants :: Single { index : FIRST_VARIANT } ,
4734 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 ( ) ,
5037 } ,
5138 abi : Abi :: ScalarPair ( a, b) ,
5239 largest_niche,
@@ -58,18 +45,18 @@ pub trait LayoutCalculator {
5845 fn univariant (
5946 & self ,
6047 dl : & TargetDataLayout ,
61- fields : & [ Layout < ' _ > ] ,
48+ fields : & IndexSlice < FieldIdx , Layout < ' _ > > ,
6249 repr : & ReprOptions ,
6350 kind : StructKind ,
6451 ) -> Option < LayoutS > {
6552 let pack = repr. pack ;
6653 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 ( ) ;
6855 let optimize = !repr. inhibit_struct_field_reordering_opt ( ) ;
6956 if optimize {
7057 let end =
7158 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] ;
7360 let effective_field_align = |layout : Layout < ' _ > | {
7461 if let Some ( pack) = pack {
7562 // return the packed alignment in bytes
@@ -105,7 +92,7 @@ pub trait LayoutCalculator {
10592 // Place ZSTs first to avoid "interesting offsets",
10693 // especially with only one or two non-ZST fields.
10794 // Then place largest alignments first, largest niches within an alignment group last
108- let f = fields[ x as usize ] ;
95+ let f = fields[ x] ;
10996 let niche_size = f. largest_niche ( ) . map_or ( 0 , |n| n. available ( dl) ) ;
11097 ( !f. 0 . is_zst ( ) , cmp:: Reverse ( effective_field_align ( f) ) , niche_size)
11198 } ) ;
@@ -117,7 +104,7 @@ pub trait LayoutCalculator {
117104 // And put the largest niche in an alignment group at the end
118105 // so it can be used as discriminant in jagged enums
119106 optimizing. sort_by_key ( |& x| {
120- let f = fields[ x as usize ] ;
107+ let f = fields[ x] ;
121108 let niche_size = f. largest_niche ( ) . map_or ( 0 , |n| n. available ( dl) ) ;
122109 ( effective_field_align ( f) , niche_size)
123110 } ) ;
@@ -135,7 +122,7 @@ pub trait LayoutCalculator {
135122 // At the bottom of this function, we invert `inverse_memory_index` to
136123 // produce `memory_index` (see `invert_mapping`).
137124 let mut sized = true ;
138- let mut offsets = vec ! [ Size :: ZERO ; fields. len ( ) ] ;
125+ let mut offsets = IndexVec :: from_elem ( Size :: ZERO , & fields) ;
139126 let mut offset = Size :: ZERO ;
140127 let mut largest_niche = None ;
141128 let mut largest_niche_available = 0 ;
@@ -146,7 +133,7 @@ pub trait LayoutCalculator {
146133 offset = prefix_size. align_to ( prefix_align) ;
147134 }
148135 for & i in & inverse_memory_index {
149- let field = & fields[ i as usize ] ;
136+ let field = & fields[ i] ;
150137 if !sized {
151138 self . delay_bug ( & format ! (
152139 "univariant: field #{} comes after unsized field" ,
@@ -168,7 +155,7 @@ pub trait LayoutCalculator {
168155 align = align. max ( field_align) ;
169156
170157 debug ! ( "univariant offset: {:?} field: {:#?}" , offset, field) ;
171- offsets[ i as usize ] = offset;
158+ offsets[ i] = offset;
172159
173160 if let Some ( mut niche) = field. largest_niche ( ) {
174161 let available = niche. available ( dl) ;
@@ -192,14 +179,18 @@ pub trait LayoutCalculator {
192179 // If field 5 has offset 0, offsets[0] is 5, and memory_index[5] should be 0.
193180 // Field 5 would be the first element, so memory_index is i:
194181 // 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+ } ;
197188 let size = min_size. align_to ( align. abi ) ;
198189 let mut abi = Abi :: Aggregate { sized } ;
199190 // Unpack newtype ABIs and find scalar pairs.
200191 if sized && size. bytes ( ) > 0 {
201192 // 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 ( ) ) ;
203194
204195 match ( non_zst_fields. next ( ) , non_zst_fields. next ( ) , non_zst_fields. next ( ) ) {
205196 // We have exactly one non-ZST field.
@@ -238,13 +229,13 @@ pub trait LayoutCalculator {
238229 let pair = self . scalar_pair ( a, b) ;
239230 let pair_offsets = match pair. fields {
240231 FieldsShape :: Arbitrary { ref offsets, ref memory_index } => {
241- assert_eq ! ( memory_index, & [ 0 , 1 ] ) ;
232+ assert_eq ! ( memory_index. raw , [ 0 , 1 ] ) ;
242233 offsets
243234 }
244235 _ => panic ! ( ) ,
245236 } ;
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 ) ]
248239 && align == pair. align
249240 && size == pair. size
250241 {
@@ -289,7 +280,7 @@ pub trait LayoutCalculator {
289280 fn layout_of_struct_or_enum (
290281 & self ,
291282 repr : & ReprOptions ,
292- variants : & IndexSlice < VariantIdx , Vec < Layout < ' _ > > > ,
283+ variants : & IndexSlice < VariantIdx , IndexVec < FieldIdx , Layout < ' _ > > > ,
293284 is_enum : bool ,
294285 is_unsafe_cell : bool ,
295286 scalar_valid_range : ( Bound < u128 > , Bound < u128 > ) ,
@@ -312,7 +303,7 @@ pub trait LayoutCalculator {
312303 // but *not* an encoding of the discriminant (e.g., a tag value).
313304 // See issue #49298 for more details on the need to leave space
314305 // for non-ZST uninhabited data (mostly partial initialization).
315- let absent = |fields : & [ Layout < ' _ > ] | {
306+ let absent = |fields : & IndexSlice < FieldIdx , Layout < ' _ > > | {
316307 let uninhabited = fields. iter ( ) . any ( |f| f. abi ( ) . is_uninhabited ( ) ) ;
317308 let is_zst = fields. iter ( ) . all ( |f| f. 0 . is_zst ( ) ) ;
318309 uninhabited && is_zst
@@ -510,7 +501,7 @@ pub trait LayoutCalculator {
510501 // It'll fit, but we need to make some adjustments.
511502 match layout. fields {
512503 FieldsShape :: Arbitrary { ref mut offsets, .. } => {
513- for ( j, offset) in offsets. iter_mut ( ) . enumerate ( ) {
504+ for ( j, offset) in offsets. iter_enumerated_mut ( ) {
514505 if !variants[ i] [ j] . 0 . is_zst ( ) {
515506 * offset += this_offset;
516507 }
@@ -577,8 +568,8 @@ pub trait LayoutCalculator {
577568 variants : IndexVec :: new ( ) ,
578569 } ,
579570 fields : FieldsShape :: Arbitrary {
580- offsets : vec ! [ niche_offset] ,
581- memory_index : vec ! [ 0 ] ,
571+ offsets : [ niche_offset] . into ( ) ,
572+ memory_index : [ 0 ] . into ( ) ,
582573 } ,
583574 abi,
584575 largest_niche,
@@ -651,7 +642,8 @@ pub trait LayoutCalculator {
651642 st. variants = Variants :: Single { index : i } ;
652643 // Find the first field we can't move later
653644 // 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) ] ;
655647 if !field. 0 . is_zst ( ) || field. align ( ) . abi . bytes ( ) != 1 {
656648 start_align = start_align. min ( field. align ( ) . abi ) ;
657649 break ;
@@ -802,13 +794,13 @@ pub trait LayoutCalculator {
802794 let pair = self . scalar_pair ( tag, prim_scalar) ;
803795 let pair_offsets = match pair. fields {
804796 FieldsShape :: Arbitrary { ref offsets, ref memory_index } => {
805- assert_eq ! ( memory_index, & [ 0 , 1 ] ) ;
797+ assert_eq ! ( memory_index. raw , [ 0 , 1 ] ) ;
806798 offsets
807799 }
808800 _ => panic ! ( ) ,
809801 } ;
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
812804 && align == pair. align
813805 && size == pair. size
814806 {
@@ -844,7 +836,10 @@ pub trait LayoutCalculator {
844836 tag_field : 0 ,
845837 variants : IndexVec :: new ( ) ,
846838 } ,
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+ } ,
848843 largest_niche,
849844 abi,
850845 align,
@@ -883,7 +878,7 @@ pub trait LayoutCalculator {
883878 fn layout_of_union (
884879 & self ,
885880 repr : & ReprOptions ,
886- variants : & IndexSlice < VariantIdx , Vec < Layout < ' _ > > > ,
881+ variants : & IndexSlice < VariantIdx , IndexVec < FieldIdx , Layout < ' _ > > > ,
887882 ) -> Option < LayoutS > {
888883 let dl = self . current_data_layout ( ) ;
889884 let dl = dl. borrow ( ) ;
0 commit comments