Skip to content
This repository was archived by the owner on Sep 11, 2023. It is now read-only.
This repository was archived by the owner on Sep 11, 2023. It is now read-only.

Strange code generated in enum_map_derive? #23

@Fuuzetsu

Description

@Fuuzetsu

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions