Yes, that's correct.
- For non-generic enums, the compiler can statically know whether a case can be written off during synthesis
- For generic enums, the types would need to be inspected at runtime, since the generics can be instantiated externally; synthesis would need to be updated in the compiler to check all generic types. This may come at an unfortunate performance cost for a very rare scenario
It does get a bit trickier, if you want to take this idea further:
Never is not the only non-instantiable type, but we don't currently to my knowledge have a formalized concept of "non-instantiable", either in the compiler or at runtime. For example:
enum MyNever {
private init() { fatalError() }
}
struct MyNonInstantiableStruct {
// Non-instantiable, because of either type:
let never1: Never
let never2: MyNever
}
The compiler knows about Never, but it doesn't know about MyNonInstantiableStruct — so .b(Never) could be avoided during decoding, but .b(MyNonInstantiableStruct) could not.
Obviously, MyNonInstantiableStruct is a useless type here, but you can easily end up with a Never deeply nested within a type hierarchy, that in the general case, the compiler would need to search for if we wanted to generalize this concept.
I think whether we should formalize this is a good question, both philosophically and practically. It's easy to do the bare minimum here and get rid of the most obvious of foot-guns, but being 100% consistent would be tricky and take more work, potentially.
Though, handling this could easily be additive — and it's quite possible that it's simply enough to have Never throw and call it a day.