Commit b0a55e1b3b
Changed files (3)
src
test
behavior
cases
compile_errors
src/Sema.zig
@@ -6789,6 +6789,15 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
error_set.fmt(sema.mod),
});
}
+ if (payload.zigTypeTag() == .Opaque) {
+ return sema.fail(block, rhs_src, "error union with payload of opaque type '{}' not allowed", .{
+ payload.fmt(sema.mod),
+ });
+ } else if (payload.zigTypeTag() == .ErrorSet) {
+ return sema.fail(block, rhs_src, "error union with payload of error set type '{}' not allowed", .{
+ payload.fmt(sema.mod),
+ });
+ }
const err_union_ty = try Type.errorUnion(sema.arena, error_set, payload, sema.mod);
return sema.addType(err_union_ty);
}
@@ -25763,6 +25772,11 @@ fn analyzeIsNonErrComptimeOnly(
if (ot == .ErrorSet) return Air.Inst.Ref.bool_false;
assert(ot == .ErrorUnion);
+ const payload_ty = operand_ty.errorUnionPayload();
+ if (payload_ty.zigTypeTag() == .NoReturn) {
+ return Air.Inst.Ref.bool_false;
+ }
+
if (Air.refToIndex(operand)) |operand_inst| {
switch (sema.air_instructions.items(.tag)[operand_inst]) {
.wrap_errunion_payload => return Air.Inst.Ref.bool_true,
test/behavior/error.zig
@@ -725,7 +725,7 @@ test "simple else prong allowed even when all errors handled" {
try expect(value == 255);
}
-test {
+test "pointer to error union payload" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
@@ -736,3 +736,63 @@ test {
const payload_ptr = &(err_union catch unreachable);
try expect(payload_ptr.* == 15);
}
+
+const NoReturn = struct {
+ var a: u32 = undefined;
+ fn someData() bool {
+ a -= 1;
+ return a == 0;
+ }
+ fn loop() !noreturn {
+ while (true) {
+ if (someData())
+ return error.GenericFailure;
+ }
+ }
+ fn testTry() anyerror {
+ try loop();
+ }
+ fn testCatch() anyerror {
+ loop() catch return error.OtherFailure;
+ @compileError("bad");
+ }
+};
+
+test "error union of noreturn used with if" {
+ if (builtin.zig_backend == .stage1) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+
+ NoReturn.a = 64;
+ if (NoReturn.loop()) {
+ @compileError("bad");
+ } else |err| {
+ try expect(err == error.GenericFailure);
+ }
+}
+
+test "error union of noreturn used with try" {
+ if (builtin.zig_backend == .stage1) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+
+ NoReturn.a = 64;
+ const err = NoReturn.testTry();
+ try expect(err == error.GenericFailure);
+}
+
+test "error union of noreturn used with catch" {
+ if (builtin.zig_backend == .stage1) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+
+ NoReturn.a = 64;
+ const err = NoReturn.testCatch();
+ try expect(err == error.OtherFailure);
+}
test/cases/compile_errors/invalid_error_union_payload_type.zig
@@ -0,0 +1,13 @@
+comptime {
+ _ = anyerror!anyopaque;
+}
+comptime {
+ _ = anyerror!anyerror;
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :2:18: error: error union with payload of opaque type 'anyopaque' not allowed
+// :5:18: error: error union with payload of error set type 'anyerror' not allowed