mirror of
https://github.com/ziglang/zig.git
synced 2024-11-25 13:50:15 +00:00
Sema: give try
operand error{}
result type in non-errorable functions
Resolves: #21414
This commit is contained in:
parent
4d81e8ee91
commit
19924ca289
18
src/Sema.zig
18
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, &.{}));
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user