Resolves #35602
Resolves https://github.com/ziglang/zig/issues/19855
This PR implements the @backingInt and @fromBackingInt builtins.
These builtins are meant to replace the now-deprecated @intFromEnum and @enumFromInt builtins.
@backingInt works with enums and bitpacks with explicit backing integer types only. It also works with tagged unions if the enum tag type has an explicitly specified backing integer, returning the backing integer of the active tag value. An undefined enum or bitpack yields an undefined backing integer. The builtin is lowered to bit_cast.
@fromBackingInt infers its result type, which may be an enum or a bitpack with an explicit backing integer type. It takes a parameter of exactly that backing integer type. For enums, passing a backing integer that is either undefined or would yield an invalid tag value results in safety-checked Illegal Behavior. For bitpacks, passing an undefined backing integer yields an undefined bitpack.
The builtin is lowered to bit_cast or bit_cast_safe (more details below).
@bitCast now also performs a safety check for invalid tag values if its destination type is an enum.
This commit also introduces a new AIR instruction, bit_cast_safe. Similarly to int_cast_safe, it includes a safety check for invalid enum tag values. When @enumFromInt is eventually removed, int_cast_safe won't need to perform this safety check anymore.
Also adds a std.meta.BackingInt() function to conveniently get the result type of @backingInt and for use in the langref.
Empty enums now also require noreturn as their backing int.
Empty enums are uninstantiable, so their backing integer should be too. This avoids a bunch of weird special cases during semantic analysis.
If you were previously using enum {}, your code should continue to work fine.
If you were previously using enum(uN) {} (where uN is any integer type), you'll probably want to use enum(uN) { _ } instead.
EDIT: For now, the new builtints continue to work with enums with inferred backing integers. This allows replacing the old builtins with the new ones without changing semantics.
Also adds a zig fmt canonicalization for @intFromEnum(x) -> @backingInt(x) and @enumFromInt(x) -> @fromBackingInt(@intCast(x)).