Allow impossible values of slice length to be used as enum discriminant

For non-ZST slices, the length of the slice is required to be <= isize::MAX.
Currently, enums containing slices like:

enum Example<'a> {
    Variant1(&'a [u8]),
    Variant2,
    Variant3
}

Have a size of 24 bytes.
Given u8 is not zero-sized, and the length should thus be <= isize::MAX, the length could double as the variant ID, allowing the size to be shrunk to 16 bytes.

An example real-world usecase would be a Value enum for (de)serializers:

pub enum Value<'de> {
    Int(u64),
    Float(f64),
    String(&'de str),
    List(u32),
    Map(u32),
    Null
}
11 Likes

Example still has to be 24 bytes even when the length has a niche for > isize::MAX. This because it must be possible to take a reference to the &[u8] field of both variants, which requires that they both have the real length stored and thus can't use the upper bit as discriminant to distinguish between the two.

True, I've updated the example, thanks for pointing it out!

This is absolutely something that everyone wants, but it's challenging because of cycles and performance -- the size of the niche depends on the size of the element type, but you could have things where the element type depends on the self type.

It'll probably need adding a "safe underestimate of the size and alignment" query, but then the problem is adding that extra query without making the compiler perf worse.

That said, the most important different is ZST-ness vs non-ZST-ness, as &[()] has no niches in the length. So maybe there's a simplified version that could get most of the niche usefulness by just doing that -- isize::MAX length niches is probably more than can realistically be used anyway, even if there could be more than that sometimes.

cc also cleanup quasi-layout alignment computations · Issue #147107 · rust-lang/rust · GitHub

8 Likes