Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add _Enum! macros to replace _ arms when matching shared enums #1376

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

nicolas-guichard
Copy link

As the docs currently state about shared enums:

Pattern matching with match still works but will require you to write wildcard arms to handle the situation of an enum value that is not one of the listed variants.

This is unfortunate as there is no way to check that all listed enum variants are actually handled. IOW this code does not even warn:

mod ffi {
    enum Enum {
        A,
        B,
        C = 5,
    }
}

match t {
    Enum::A => {},
    Enum::B => {},
    _ => {},
}

This generates an extra _Enum! macro that matches all the ranges that are not listed by the enum. When using that macro instead of the _ catch-all, we get compile-time errors if we forget to match variants:

match t {
    Enum::A => {},
    Enum::B => {},
    _Enum!() => {},
}
// Error Enum{ repr: 5 } case not covered

The generated macro looks like:

macro_rules! _Enum {
    () => { Enum{ repr: 4..5 | 6.. } };
    ($i:ident) => { Enum { repr: $i @ 4..5 | 6.. } };
}

It can also be used to ergonomically retrieve the inner value in the unlisted case:

match t {
    Enum::A => {},
    Enum::B => {},
    Enum::C => {},
    _Enum!(value) => panic!("Unexpected Enum value {value}"),
}

I would have preferred something like Enum::unlisted!, but macro definitions are not supported in impls. I think _Enum carries the meaning of _ specific to Enum, but I'm open to other naming/namespacing ideas.

As the docs currently state about shared enums:
> Pattern matching with match still works but will require you to write
> wildcard arms to handle the situation of an enum value that is not
> one of the listed variants.

This is unfortunate as there is no way to check that all listed enum
variants are actually handled. IOW this code does not even warn:
```
mod ffi {
    enum Enum {
        A,
        B,
        C = 5,
    }
}

match t {
    Enum::A => {},
    Enum::B => {},
    _ => {},
}
```

This generates an extra _Enum! macro that matches all the ranges that
are _not_ listed by the enum. When using that macro instead of the _
catch-all, we get compile-time errors if we forget to match variants:
```
match t {
    Enum::A => {},
    Enum::B => {},
    _Enum!() => {},
}
// Error Enum{ repr: 5 } case not covered
```

The generated macro looks like:
```
macro_rules! _Enum {
    () => { Enum{ repr: 4..5 | 6.. } };
    ($i:ident) => { Enum { repr: $i @ 4..5 | 6.. } };
}
```

It can also be used to ergonomically retrieve the inner value in the
unlisted case:
```
match t {
    Enum::A => {},
    Enum::B => {},
    Enum::C => {},
    _Enum!(value) => panic!("Unexpected Enum value {value}"),
}
```
Limits::of(atom).expect("Unexpected EnumRepr")
}
#[cfg(feature = "experimental-enum-variants-from-header")]
&EnumRepr::Foreign { rust_type: _ } => todo!(),
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NB: this TODO should obviously be fixed before this can be merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant