@@ -103,11 +103,19 @@ enum Option2<A, B> {
103103 None
104104}
105105
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.
106114pub enum CanBeNicheFilledButShouldnt {
107115 A ( NonZeroU8 , u32 ) ,
108116 B
109117}
110- pub enum AlwaysTagged {
118+ pub enum AlwaysTaggedBecauseItHasNoNiche {
111119 A ( u8 , u32 ) ,
112120 B
113121}
@@ -159,7 +167,7 @@ pub fn main() {
159167 assert_eq ! ( size_of:: <CanBeNicheFilledButShouldnt >( ) , 8 ) ;
160168 assert_eq ! ( size_of:: <Option <CanBeNicheFilledButShouldnt >>( ) , 8 ) ;
161169 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 ) ;
165173}
0 commit comments