mirror of
https://github.com/ziglang/zig.git
synced 2025-12-31 18:43:18 +00:00
Sema: allow simple else body even when all errors handled
This commit is contained in:
parent
d5e3d5d74c
commit
e4c0b848a4
30
src/Sema.zig
30
src/Sema.zig
@ -7774,7 +7774,12 @@ fn zirSwitchCapture(
|
||||
}
|
||||
|
||||
switch (operand_ty.zigTypeTag()) {
|
||||
.ErrorSet => return sema.bitCast(block, block.switch_else_err_ty.?, operand, operand_src),
|
||||
.ErrorSet => if (block.switch_else_err_ty) |some| {
|
||||
return sema.bitCast(block, some, operand, operand_src);
|
||||
} else {
|
||||
try block.addUnreachable(operand_src, false);
|
||||
return Air.Inst.Ref.unreachable_value;
|
||||
},
|
||||
else => return operand,
|
||||
}
|
||||
}
|
||||
@ -8194,7 +8199,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
||||
);
|
||||
}
|
||||
else_error_ty = Type.@"anyerror";
|
||||
} else {
|
||||
} else else_validation: {
|
||||
var maybe_msg: ?*Module.ErrorMsg = null;
|
||||
errdefer if (maybe_msg) |msg| msg.destroy(sema.gpa);
|
||||
|
||||
@ -8231,6 +8236,27 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
||||
}
|
||||
|
||||
if (special_prong == .@"else" and seen_errors.count() == operand_ty.errorSetNames().len) {
|
||||
|
||||
// In order to enable common patterns for generic code allow simple else bodies
|
||||
// else => unreachable,
|
||||
// else => return,
|
||||
// else => |e| return e,
|
||||
// even if all the possible errors were already handled.
|
||||
const tags = sema.code.instructions.items(.tag);
|
||||
for (special.body) |else_inst| switch (tags[else_inst]) {
|
||||
.dbg_block_begin,
|
||||
.dbg_block_end,
|
||||
.dbg_stmt,
|
||||
.dbg_var_val,
|
||||
.switch_capture,
|
||||
.ret_type,
|
||||
.as_node,
|
||||
.ret_node,
|
||||
.@"unreachable",
|
||||
=> {},
|
||||
else => break,
|
||||
} else break :else_validation;
|
||||
|
||||
return sema.fail(
|
||||
block,
|
||||
special_prong_src,
|
||||
|
||||
@ -769,3 +769,30 @@ test "ret_ptr doesn't cause own inferred error set to be resolved" {
|
||||
};
|
||||
try S.doTheTest();
|
||||
}
|
||||
|
||||
test "simple else prong allowed even when all errors handled" {
|
||||
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
|
||||
|
||||
const S = struct {
|
||||
fn foo() !u8 {
|
||||
return error.Foo;
|
||||
}
|
||||
};
|
||||
var value = S.foo() catch |err| switch (err) {
|
||||
error.Foo => 255,
|
||||
else => |e| return e,
|
||||
};
|
||||
try expect(value == 255);
|
||||
value = S.foo() catch |err| switch (err) {
|
||||
error.Foo => 255,
|
||||
else => unreachable,
|
||||
};
|
||||
try expect(value == 255);
|
||||
value = S.foo() catch |err| switch (err) {
|
||||
error.Foo => 255,
|
||||
else => return,
|
||||
};
|
||||
try expect(value == 255);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user