Commit f281f3d10e

Veikka Tuominen <git@vexu.eu>
2022-09-02 15:08:20
Sema: improve behavior of comptime_int backed enums
1 parent a9cdacf
Changed files (4)
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;
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);
+}
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);
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