aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2022-09-02 16:08:20 +0300
committerVeikka Tuominen <git@vexu.eu>2022-09-02 17:57:11 +0300
commitf281f3d10e4eaedc7c68afc4fcbbfd35e1f29a0f (patch)
tree3a28628a95126b07fe7fa17e12ff3cbab1e9df65
parenta9cdacff95a2a6f60945c7b2a299f9f66bd94ddb (diff)
downloadzig-f281f3d10e4eaedc7c68afc4fcbbfd35e1f29a0f.tar.gz
zig-f281f3d10e4eaedc7c68afc4fcbbfd35e1f29a0f.zip
Sema: improve behavior of comptime_int backed enums
-rw-r--r--src/Sema.zig7
-rw-r--r--test/behavior/enum.zig7
-rw-r--r--test/behavior/union.zig2
-rw-r--r--test/cases/compile_errors/enum_backed_by_comptime_int_must_be_comptime.zig11
4 files changed, 23 insertions, 4 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 1ee5bf71b1..6966060842 100644
--- 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
index 517414780b..28c8785e64 100644
--- 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
index 9053a860a6..b94034adf4 100644
--- 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
new file mode 100644
index 0000000000..7dab294d4a
--- /dev/null
+++ 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