@@ -103,11 +103,19 @@ enum Option2<A, B> {
103
103
None
104
104
}
105
105
106
+ // Two layouts are considered for `CanBeNicheFilledButShouldnt`:
107
+ // Niche-filling:
108
+ // { u32 (4 bytes), NonZeroU8 + tag in niche (1 byte), padding (3 bytes) }
109
+ // Tagged:
110
+ // { tag (1 byte), NonZeroU8 (1 byte), padding (2 bytes), u32 (4 bytes) }
111
+ // Both are the same size (due to padding),
112
+ // but the tagged layout is better as the tag creates a niche with 254 invalid values,
113
+ // allowing types like `Option<Option<CanBeNicheFilledButShouldnt>>` to fit into 8 bytes.
106
114
pub enum CanBeNicheFilledButShouldnt {
107
115
A ( NonZeroU8 , u32 ) ,
108
116
B
109
117
}
110
- pub enum AlwaysTagged {
118
+ pub enum AlwaysTaggedBecauseItHasNoNiche {
111
119
A ( u8 , u32 ) ,
112
120
B
113
121
}
@@ -159,7 +167,7 @@ pub fn main() {
159
167
assert_eq ! ( size_of:: <CanBeNicheFilledButShouldnt >( ) , 8 ) ;
160
168
assert_eq ! ( size_of:: <Option <CanBeNicheFilledButShouldnt >>( ) , 8 ) ;
161
169
assert_eq ! ( size_of:: <Option <Option <CanBeNicheFilledButShouldnt >>>( ) , 8 ) ;
162
- assert_eq ! ( size_of:: <AlwaysTagged >( ) , 8 ) ;
163
- assert_eq ! ( size_of:: <Option <AlwaysTagged >>( ) , 8 ) ;
164
- assert_eq ! ( size_of:: <Option <Option <AlwaysTagged >>>( ) , 8 ) ;
170
+ assert_eq ! ( size_of:: <AlwaysTaggedBecauseItHasNoNiche >( ) , 8 ) ;
171
+ assert_eq ! ( size_of:: <Option <AlwaysTaggedBecauseItHasNoNiche >>( ) , 8 ) ;
172
+ assert_eq ! ( size_of:: <Option <Option <AlwaysTaggedBecauseItHasNoNiche >>>( ) , 8 ) ;
165
173
}
0 commit comments