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...@@ -22626,20 +22626,18 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
22626 const base_operand_ty = sema.typeOf(operand);22626 const base_operand_ty = sema.typeOf(operand);
22627 const dest_tag = base_dest_ty.zigTypeTag(mod);22627 const dest_tag = base_dest_ty.zigTypeTag(mod);
22628 const operand_tag = base_operand_ty.zigTypeTag(mod);22628 const operand_tag = base_operand_ty.zigTypeTag(mod);
22629 if (dest_tag != operand_tag) {22629
22630 return sema.fail(block, src, "expected source and destination types to match, found '{s}' and '{s}'", .{22630 if (dest_tag != .ErrorSet and dest_tag != .ErrorUnion) {
22631 @tagName(operand_tag), @tagName(dest_tag),
22632 });
22633 } else if (dest_tag != .ErrorSet and dest_tag != .ErrorUnion) {
22634 return sema.fail(block, src, "expected error set or error union type, found '{s}'", .{@tagName(dest_tag)});22631 return sema.fail(block, src, "expected error set or error union type, found '{s}'", .{@tagName(dest_tag)});
22635 }22632 }
22636 const dest_ty, const operand_ty = if (dest_tag == .ErrorUnion) .{22633 if (operand_tag != .ErrorSet and operand_tag != .ErrorUnion) {
22637 base_dest_ty.errorUnionSet(mod),22634 return sema.fail(block, src, "expected error set or error union type, found '{s}'", .{@tagName(operand_tag)});
22638 base_operand_ty.errorUnionSet(mod),22635 }
22639 } else .{22636 if (dest_tag == .ErrorSet and operand_tag == .ErrorUnion) {
22640 base_dest_ty,22637 return sema.fail(block, src, "cannot cast an error union type to error set", .{});
22641 base_operand_ty,22638 }
22642 };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
22644 // operand must be defined since it can be an invalid error value22642 // operand must be defined since it can be an invalid error value
22645 const maybe_operand_val = try sema.resolveDefinedValue(block, operand_src, operand);22643 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...@@ -22681,7 +22679,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
22681 if (!dest_ty.isAnyError(mod)) check: {22679 if (!dest_ty.isAnyError(mod)) check: {
22682 const operand_val = mod.intern_pool.indexToKey(val.toIntern());22680 const operand_val = mod.intern_pool.indexToKey(val.toIntern());
22683 var error_name: InternPool.NullTerminatedString = undefined;22681 var error_name: InternPool.NullTerminatedString = undefined;
22684 if (dest_tag == .ErrorUnion) {22682 if (operand_tag == .ErrorUnion) {
22685 if (operand_val.error_union.val != .err_name) break :check;22683 if (operand_val.error_union.val != .err_name) break :check;
22686 error_name = operand_val.error_union.val.err_name;22684 error_name = operand_val.error_union.val.err_name;
22687 } else {22685 } else {
test/behavior/error.zig+5
...@@ -1039,3 +1039,8 @@ test "errorCast to adhoc inferred error set" {...@@ -1039,3 +1039,8 @@ test "errorCast to adhoc inferred error set" {
1039 };1039 };
1040 try std.testing.expect((try S.baz()) == 1234);1040 try std.testing.expect((try S.baz()) == 1234);
1041}1041}
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