authorgravatar for iodizon@163.comHydroH <iodizon@163.com> 2024-03-28 18:23:32+08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-03-28 10:23:32+00:00
log7aa42f47b79f289829a1b43a68c8c08e374aa6a2
treeb4562be62e7f23bad2ed9429fa6451871b65ff4a
parent17053887d080bd125d2f5ccbb39238f23c706328
signaturebadge-check Signed by PGP key B5690EEEBB952194

allow `@errorcast` to cast error sets to error unions


3 files changed, 39 insertions(+), 13 deletions(-)

src/Sema.zig+11-13
......@@ -22626,20 +22626,18 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
2262622626 const base_operand_ty = sema.typeOf(operand);
2262722627 const dest_tag = base_dest_ty.zigTypeTag(mod);
2262822628 const operand_tag = base_operand_ty.zigTypeTag(mod);
22629 if (dest_tag != operand_tag) {
22630 return sema.fail(block, src, "expected source and destination types to match, found '{s}' and '{s}'", .{
22631 @tagName(operand_tag), @tagName(dest_tag),
22632 });
22633 } else if (dest_tag != .ErrorSet and dest_tag != .ErrorUnion) {
22629
22630 if (dest_tag != .ErrorSet and dest_tag != .ErrorUnion) {
2263422631 return sema.fail(block, src, "expected error set or error union type, found '{s}'", .{@tagName(dest_tag)});
2263522632 }
22636 const dest_ty, const operand_ty = if (dest_tag == .ErrorUnion) .{
22637 base_dest_ty.errorUnionSet(mod),
22638 base_operand_ty.errorUnionSet(mod),
22639 } else .{
22640 base_dest_ty,
22641 base_operand_ty,
22642 };
22633 if (operand_tag != .ErrorSet and operand_tag != .ErrorUnion) {
22634 return sema.fail(block, src, "expected error set or error union type, found '{s}'", .{@tagName(operand_tag)});
22635 }
22636 if (dest_tag == .ErrorSet and operand_tag == .ErrorUnion) {
22637 return sema.fail(block, src, "cannot cast an error union type to error set", .{});
22638 }
22639 const dest_ty = if (dest_tag == .ErrorUnion) base_dest_ty.errorUnionSet(mod) else base_dest_ty;
22640 const operand_ty = if (operand_tag == .ErrorUnion) base_operand_ty.errorUnionSet(mod) else base_operand_ty;
2264322641
2264422642 // operand must be defined since it can be an invalid error value
2264522643 const maybe_operand_val = try sema.resolveDefinedValue(block, operand_src, operand);
......@@ -22681,7 +22679,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
2268122679 if (!dest_ty.isAnyError(mod)) check: {
2268222680 const operand_val = mod.intern_pool.indexToKey(val.toIntern());
2268322681 var error_name: InternPool.NullTerminatedString = undefined;
22684 if (dest_tag == .ErrorUnion) {
22682 if (operand_tag == .ErrorUnion) {
2268522683 if (operand_val.error_union.val != .err_name) break :check;
2268622684 error_name = operand_val.error_union.val.err_name;
2268722685 } else {
test/behavior/error.zig+5
......@@ -1039,3 +1039,8 @@ test "errorCast to adhoc inferred error set" {
10391039 };
10401040 try std.testing.expect((try S.baz()) == 1234);
10411041}
1042
1043test "errorCast from error sets to error unions" {
1044 const err_union: Set1!void = @errorCast(error.A);
1045 try expectError(error.A, err_union);
1046}
test/cases/compile_errors/@errorCast_with_bad_type.zig created+23
......@@ -0,0 +1,23 @@
1const err = error.Foo;
2
3export fn entry1() void {
4 const a: anyerror = @errorCast(1);
5 _ = a;
6}
7export fn entry2() void {
8 const a: i32 = @errorCast(err);
9 _ = a;
10}
11export fn entry3() void {
12 const e: anyerror!void = err;
13 const a: anyerror = @errorCast(e);
14 _ = a;
15}
16
17// error
18// backend=stage2
19// target=x86_64-linux
20//
21// :4:25: error: expected error set or error union type, found 'ComptimeInt'
22// :8:20: error: expected error set or error union type, found 'Int'
23// :13:25: error: cannot cast an error union type to error set