A simpler alternative here is to just have:
ty ::= ... | ty_senum ;
ty_senum : "(" (ty "|")+ (ty "|"?)? ")" ;
as @CAD97 has noted.
The changes to the expression and pattern grammars are not defined.
Ostensibly you could write if let _::0(x, y, ...) = expr { .. }
otherwise which seems more ergonomic and probably necessary to make it more ergonomic than creating new nominally typed enums.
This is not ambiguous, but requires at least backtracking with https://github.com/rust-lang/rfcs/pull/2535. Worse, the backtracking here is not a corner case that is unlikely to arise, rather, it is quite likely to occur.
The most powerful solution is probably frunk::coproduct - Rust and should be mentioned.
Another way to have structurally typed coproducts is to have something like:
type Foo = Bar | Bar(u8, f32) | Quux { field: String };
let a_foo: Foo = Bar(1, 1.0);
match a_foo {
Bar => expr,
Bar(x, y) => expr,
Quux { field } => expr,
}
As you can see, there are zero changes to the pattern and expression grammars. Only the type grammar changes.