The compiler knows to store the nil case as zero pointer (0x00000000). Some enum also behave this way if the compiler can proof that there's an "impossible" case. That said, I don't know the precise criteria, nor do I know if it'll stay that way (though it's very likely).
As noted above, often wrapping enums do not add bytes. While it’s been pointed out that in the pointer case this is necessary, it’s a broader fact that applies throughout Swift. The Swift compiler has awareness of “extra inhabitants”: values of a type that are not in range for those values. It also knows about unused bits of types. This leads to lots of packing efficiencies.
It's interesting that this topic is coming up now, because I encountered a situation recently where I hoped Swift would optimise this kind of layout, but it didn't.
Basically, if I have a struct containing lots of optionals, I'd like it to coalesce all of the discriminators as a single byte. So given a type:
struct Test {
var a: Int8?
var b: Int8?
var c: Int8?
var d: Int8?
}
Currently, MemoryLayout<Test>.size == 8 because it's stored as 4 independent optionals, and MemoryLayout<Int8?> is 2. I wish it would be 5 (4 bytes + 1 byte containing all of their discriminators).
IIRC, Swift leaves room for those kind of optimisations to be introduced at some point. I'm a little worried because I think MemoryLayout<T>.offset(of:) might prohibit it.
There's no formal guarantee that a stored property has an addressable offset; if a property is reabstracted, or has observers, for instance, then offset(of:) returns nil for that property. It's likely that a future compiler would require some annotation for properties that have to be addressable, because in the general case it would be better to be able to optimize the layout of structs using overlapping and/or interleaved storage.