If we have an enum like this:
pub enum Scens {
Zero,
One,
Two,
Three,
Four,
Five,
}
doing #[derive(Enum)]
produces code that looks like this:
pub fn from_usize(v: usize) -> Scens {
use Scens::*;
if v < 1 {
Zero
} else if v < 2 {
One
} else if v < 3 {
Two
} else if v < 4 {
Three
} else if v < 5 {
Four
} else if v < 6 {
Five
} else {
unreachable!()
}
}
This seems strange to me and the compiler: building with optimisation results in a large chain of comparisons and conditional jumps.
If instead we would generate
pub fn from_usize(v: usize) -> Scens {
use Scens::*;
if v == 0 {
Zero
} else if v == 1 {
One
} else if v == 2 {
Two
} else if v == 3 {
Three
} else if v == 4 {
Four
} else if v == 5 {
Five
} else {
unreachable!()
}
}
or the less-verbose
pub fn from_usize(v: usize) -> Scens {
use Scens::*;
match v {
0 => Zero,
1 => One,
2 => Two,
3 => Three,
4 => Four,
5 => Five,
_ => unreachable!()
}
}
both of these produce simpler and faster code: check if the value is in range (< 6 in this case
) and then accept an answer as-is.
However I assume the if v < x + 1
implementation wasn't pick at random: is there some information about this? Is there a downside of the proposed methods? It seems very simple to switch the code over to equality check which compiler is much happier about.
These generated methods are quite hot in our code-base which is how I stumbled upon this.
Godbolt link: https://rust.godbolt.org/z/a7E3oE81s
bug