authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-06-07 17:48:53+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-06-07 21:27:06+03:00
loge4c0b848a46347fccced787488605ac66e83c38a
tree205051772acd480b8c85182ddc3786123d88c0d9
parentd5e3d5d74cefd64287b92d148f78353cdb84e447

Sema: allow simple else body even when all errors handled


2 files changed, 55 insertions(+), 2 deletions(-)

src/Sema.zig+28-2
...@@ -7774,7 +7774,12 @@ fn zirSwitchCapture(...@@ -7774,7 +7774,12 @@ fn zirSwitchCapture(
7774 }7774 }
77757775
7776 switch (operand_ty.zigTypeTag()) {7776 switch (operand_ty.zigTypeTag()) {
7777 .ErrorSet => return sema.bitCast(block, block.switch_else_err_ty.?, operand, operand_src),7777 .ErrorSet => if (block.switch_else_err_ty) |some| {
7778 return sema.bitCast(block, some, operand, operand_src);
7779 } else {
7780 try block.addUnreachable(operand_src, false);
7781 return Air.Inst.Ref.unreachable_value;
7782 },
7778 else => return operand,7783 else => return operand,
7779 }7784 }
7780 }7785 }
...@@ -8194,7 +8199,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8194,7 +8199,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8194 );8199 );
8195 }8200 }
8196 else_error_ty = Type.@"anyerror";8201 else_error_ty = Type.@"anyerror";
8197 } else {8202 } else else_validation: {
8198 var maybe_msg: ?*Module.ErrorMsg = null;8203 var maybe_msg: ?*Module.ErrorMsg = null;
8199 errdefer if (maybe_msg) |msg| msg.destroy(sema.gpa);8204 errdefer if (maybe_msg) |msg| msg.destroy(sema.gpa);
82008205
...@@ -8231,6 +8236,27 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8231,6 +8236,27 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8231 }8236 }
82328237
8233 if (special_prong == .@"else" and seen_errors.count() == operand_ty.errorSetNames().len) {8238 if (special_prong == .@"else" and seen_errors.count() == operand_ty.errorSetNames().len) {
8239
8240 // In order to enable common patterns for generic code allow simple else bodies
8241 // else => unreachable,
8242 // else => return,
8243 // else => |e| return e,
8244 // even if all the possible errors were already handled.
8245 const tags = sema.code.instructions.items(.tag);
8246 for (special.body) |else_inst| switch (tags[else_inst]) {
8247 .dbg_block_begin,
8248 .dbg_block_end,
8249 .dbg_stmt,
8250 .dbg_var_val,
8251 .switch_capture,
8252 .ret_type,
8253 .as_node,
8254 .ret_node,
8255 .@"unreachable",
8256 => {},
8257 else => break,
8258 } else break :else_validation;
8259
8234 return sema.fail(8260 return sema.fail(
8235 block,8261 block,
8236 special_prong_src,8262 special_prong_src,
test/behavior/error.zig+27
...@@ -769,3 +769,30 @@ test "ret_ptr doesn't cause own inferred error set to be resolved" {...@@ -769,3 +769,30 @@ test "ret_ptr doesn't cause own inferred error set to be resolved" {
769 };769 };
770 try S.doTheTest();770 try S.doTheTest();
771}771}
772
773test "simple else prong allowed even when all errors handled" {
774 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
775 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
776 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
777
778 const S = struct {
779 fn foo() !u8 {
780 return error.Foo;
781 }
782 };
783 var value = S.foo() catch |err| switch (err) {
784 error.Foo => 255,
785 else => |e| return e,
786 };
787 try expect(value == 255);
788 value = S.foo() catch |err| switch (err) {
789 error.Foo => 255,
790 else => unreachable,
791 };
792 try expect(value == 255);
793 value = S.foo() catch |err| switch (err) {
794 error.Foo => 255,
795 else => return,
796 };
797 try expect(value == 255);
798}