Hacker News new | ask | show | jobs
by tialaramex 756 days ago
> (under the hood, all of those are just a C-style union bundled with a tag field which identifies the active content of the union)

Crucially that's not necessarily what's going on in Rust and (assuming it lands) won't be the actual implementation of C++ std::optional<T&> specialisation.

Instead the language can decide from the value which type it has. This is where Rust's Guaranteed Niche Optimisation kicks in. If we've promised the compiler that type T's values don't occupy the space needed fully, the GNO promises that sum types consisting of T plus one other value are the same size as T was. There is no "tag field".

In practice, the compiler can provide optimisations beyond the Guarantee. For example the compiler can see that OwnedFd (a file descriptor) has a niche so Option<OwnedFd> is the same size as OwnedFd (ie the same size as a C integer, typically 4 bytes), but it can also see that char has a huge niche. Many of the 32 bits aren't needed to store a 21-bit Unicode scalar value, so (although the guarantee doesn't apply) a sum type of a char and six hundred other named possibilities is the same size as just the char was.

Ah, I see you mention this at the end, I think it's worth highlighting much earlier, that the "tag" isn't actually a mechanically necessary part of such a type.