Can't you use @ to bind any part of the match you want to use?
https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html#-...
https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html#-...
In following code, it would be nice if the second match could use the early return from the first match to avoid extra checks. It would also be nice if it worked across function boundaries. It would help removing boilerplate conversions or some `unreachable!()` branches.
enum Auth { Guest, User(u32), Bot(u32) }
fn check_permissions(Auth &auth) -> Result<Permission, PermissionError> {
match auth {
Auth::Guest => return PermissionError::Unauthorized,
Auth::User(_) | Auth::Bot(_) => { ... }
// ...
match auth {
Auth::User(_) => {...}
Auth::Bot(_) => {...}
// At this point the compiler should know that `Auth::Guest` is not possible
} enum Auth { Guest, User(u32), Bot(u32) }
was just syntactic sugar for struct Auth::Guest;
struct Auth::User(u32);
struct Auth::Bot(u32);
type Auth = Auth::Guest | Auth::User | Auth::Bot;
where `|` denotes an anonymous union. Using enums feel very clunky when you start needing to work with subsets of them.The pattern type work I mentioned earlier would bring us very close to what you have at the end:
enum Auth { Guest, User(u32), Bot(u32) }
type FullAuth = pattern_type!(Auth, Auth::Guest | Auth::User(_) | Auth::Bot(_)); // useless, but works
type IdAuth = pattern_type!(Auth, Auth::User(_) | Auth::Bot(_));
The full enum still needs to be defined. In particular, it serves as the basis the in-memory representation. All the subset can be handled by the compiler though.