Commit 19924ca289
src/Sema.zig
@@ -4487,7 +4487,7 @@ fn zirTryOperandTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: boo
break :ty operand_ty.childType(zcu);
} else operand_ty;
- const err_set_ty = err_set: {
+ const err_set_ty: Type = err_set: {
// There are awkward cases, like `?E`. Our strategy is to repeatedly unwrap optionals
// until we hit an error union or set.
var cur_ty = sema.fn_ret_ty;
@@ -4496,16 +4496,12 @@ fn zirTryOperandTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: boo
.error_set => break :err_set cur_ty,
.error_union => break :err_set cur_ty.errorUnionSet(zcu),
.optional => cur_ty = cur_ty.optionalChild(zcu),
- else => return sema.failWithOwnedErrorMsg(block, msg: {
- const msg = try sema.errMsg(src, "expected '{}', found error set", .{sema.fn_ret_ty.fmt(pt)});
- errdefer msg.destroy(sema.gpa);
- const ret_ty_src: LazySrcLoc = .{
- .base_node_inst = sema.getOwnerFuncDeclInst(),
- .offset = .{ .node_offset_fn_type_ret_ty = 0 },
- };
- try sema.errNote(ret_ty_src, msg, "function cannot return an error", .{});
- break :msg msg;
- }),
+ else => {
+ // This function cannot return an error.
+ // `try` is still valid if the error case is impossible, i.e. no error is returned.
+ // So, the result type has an error set of `error{}`.
+ break :err_set .fromInterned(try zcu.intern_pool.getErrorSetType(zcu.gpa, pt.tid, &.{}));
+ },
}
}
};
test/behavior/try.zig
@@ -86,3 +86,40 @@ test "try forwards result location" {
try expect((S.foo(false) catch return error.TestUnexpectedResult) == 123);
try std.testing.expectError(error.Foo, S.foo(true));
}
+
+test "'return try' of empty error set in function returning non-error" {
+ if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
+ 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_spirv64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
+
+ const S = struct {
+ fn succeed0() error{}!u32 {
+ return 123;
+ }
+ fn succeed1() !u32 {
+ return 456;
+ }
+ fn tryNoError0() u32 {
+ return try succeed0();
+ }
+ fn tryNoError1() u32 {
+ return try succeed1();
+ }
+ fn tryNoError2() u32 {
+ const e: error{}!u32 = 789;
+ return try e;
+ }
+ fn doTheTest() !void {
+ const res0 = tryNoError0();
+ const res1 = tryNoError1();
+ const res2 = tryNoError2();
+ try expect(res0 == 123);
+ try expect(res1 == 456);
+ try expect(res2 == 789);
+ }
+ };
+ try S.doTheTest();
+ try comptime S.doTheTest();
+}