Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't Rust able to optimise a match on a specific error as well as it does for is_err()? [duplicate]

Consider this silly enum:

enum Number {
    Rational {
        numerator: i32,
        denominator: std::num::NonZeroU32,
    },
    FixedPoint {
        whole: i16,
        fractional: u16,
    },
}

The data in the Rational variant takes up 8 bytes, and the data in the FixedPoint variant takes up 4 bytes. The Rational variant has a field which must be nonzero, so i would hope that the enum layout rules would use that as a discriminator, with zero indicating the presence of the FixedPoint variant.

However, this:

fn main() {
    println!("Number = {}", std::mem::size_of::<Number>(),);
}

Prints:

Number = 12

So, the enum gets space for an explicit discriminator, rather than exploiting the presence of the nonzero field.

Why isn't the compiler able to make this enum smaller?

like image 627
Tom Anderson Avatar asked Nov 17 '22 02:11

Tom Anderson


1 Answers

Although simple cases like Option<&T> can be handled without reserving space for the tag, the layout calculator in rustc is still not clever enough to optimize the size of enums with multiple non-empty variants.

This is issue #46213 on GitHub.

The case you ask about is pretty clear-cut, but there are similar cases where an enum looks like it should be optimized, but in fact can't be because the optimization would preclude taking internal references; for example, see Why does Rust use two bytes to represent this enum when only one is necessary?

like image 166
trent Avatar answered Dec 31 '22 10:12

trent