Padding bytes cannot contain niches, because:
Suppose you have an &mut Foo
pointing at the value of an Option<Foo>
. It's allowed to assign to this Foo
by copying mem::size_of::<Foo>()
bytes (4 bytes), which would then overwrite the discriminant if it were stored there.
In general, only byte values that cannot be a part of a valid value of Foo
can be used as a niche in Foo
. Padding bytes are allowed to be anything, so they cannot make the value invalid, so the Option
can't rely on the Foo
user not writing the None
-niche-value to them.
Bar
gets optimized because the c
byte has two valid values (0 and 1) and 254 invalid values, so Option
gets to pick any one of the invalid values for its use, and rely on it not being overwritten by writing a valid bool
because a valid bool
can never have anything but 0 or 1 there.