zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit f281f3d10e4eaedc7c68afc4fcbbfd35e1f29a0f (tree)
parent a9cdacff95a2a6f60945c7b2a299f9f66bd94ddb
Author: Veikka Tuominen <git@vexu.eu>
Date:   Fri,  2 Sep 2022 16:08:20 +0300

Sema: improve behavior of comptime_int backed enums

Diffstat:
Msrc/Sema.zig | 7++++---
Mtest/behavior/enum.zig | 7+++++++
Mtest/behavior/union.zig | 2+-
Atest/cases/compile_errors/enum_backed_by_comptime_int_must_be_comptime.zig | 11+++++++++++
4 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/src/Sema.zig b/src/Sema.zig @@ -2565,7 +2565,7 @@ fn zirEnumDecl( } } - if (small.nonexhaustive) { + if (small.nonexhaustive and enum_obj.tag_ty.zigTypeTag() != .ComptimeInt) { if (fields_len > 1 and std.math.log2_int(u64, fields_len) == enum_obj.tag_ty.bitSize(sema.mod.getTarget())) { return sema.fail(block, src, "non-exhaustive enum specifies every value", .{}); } @@ -20363,12 +20363,13 @@ fn validateRunTimeType( .Int, .Float, .ErrorSet, - .Enum, .Frame, .AnyFrame, .Void, => return true, + .Enum => return !(try sema.typeRequiresComptime(block, src, ty)), + .BoundFn, .ComptimeFloat, .ComptimeInt, @@ -29049,7 +29050,7 @@ pub fn typeHasOnePossibleValue( }, .enum_nonexhaustive => { const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty; - if (!(try sema.typeHasRuntimeBits(block, src, tag_ty))) { + if (tag_ty.zigTypeTag() != .ComptimeInt and !(try sema.typeHasRuntimeBits(block, src, tag_ty))) { return Value.zero; } else { return null; diff --git a/test/behavior/enum.zig b/test/behavior/enum.zig @@ -1175,3 +1175,10 @@ test "Non-exhaustive enum with nonstandard int size behaves correctly" { const E = enum(u15) { _ }; try expect(@sizeOf(E) == @sizeOf(u15)); } + +test "Non-exhaustive enum backed by comptime_int" { + const E = enum(comptime_int) { a, b, c, _ }; + comptime var e: E = .a; + e = @intToEnum(E, 378089457309184723749); + try expect(@enumToInt(e) == 378089457309184723749); +} diff --git a/test/behavior/union.zig b/test/behavior/union.zig @@ -690,7 +690,7 @@ test "union with only 1 field casted to its enum type which has enum value speci var e = Expr{ .Literal = Literal{ .Bool = true } }; comptime try expect(Tag(ExprTag) == comptime_int); - var t = @as(ExprTag, e); + comptime var t = @as(ExprTag, e); try expect(t == Expr.Literal); try expect(@enumToInt(t) == 33); comptime try expect(@enumToInt(t) == 33); diff --git a/test/cases/compile_errors/enum_backed_by_comptime_int_must_be_comptime.zig b/test/cases/compile_errors/enum_backed_by_comptime_int_must_be_comptime.zig @@ -0,0 +1,11 @@ +pub export fn entry() void { + const E = enum(comptime_int) { a, b, c, _ }; + var e: E = .a; + _ = e; +} + +// error +// backend=stage2 +// target=native +// +// :3:12: error: variable of type 'tmp.entry.E' must be const or comptime