mirror of
https://github.com/ziglang/zig.git
synced 2026-02-20 00:08:56 +00:00
Sema: make noreturn error union behave correctly
This commit is contained in:
parent
db0f372da8
commit
b0a55e1b3b
14
src/Sema.zig
14
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,
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
Loading…
x
Reference in New Issue
Block a user