From 879c3d1fc4822a9443f0403367c353fb2dc9b746 Mon Sep 17 00:00:00 2001 From: dweiller <4678790+dweiller@users.noreply.github.com> Date: Thu, 9 May 2024 01:37:36 +1000 Subject: [PATCH 1/4] astgen: fix result info for catch switch_block_err_union --- lib/std/zig/AstGen.zig | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index 9be6a9f60597..905fa4bdc274 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -7071,8 +7071,10 @@ fn switchExprErrUnion( .ctx = ri.ctx, }; - const payload_is_ref = node_ty == .@"if" and - if_full.payload_token != null and token_tags[if_full.payload_token.?] == .asterisk; + const payload_is_ref = switch (node_ty) { + .@"if" => if_full.payload_token != null and token_tags[if_full.payload_token.?] == .asterisk, + .@"catch" => ri.rl == .ref or ri.rl == .ref_coerced_ty, + }; // We need to call `rvalue` to write through to the pointer only if we had a // result pointer and aren't forwarding it. From 368b94f82d4c1a5668cbc1618572f7e958745e96 Mon Sep 17 00:00:00 2001 From: dweiller <4678790+dweiller@users.noreply.github.com> Date: Thu, 9 May 2024 02:54:15 +1000 Subject: [PATCH 2/4] test: import missing error union switch behavior tests --- test/behavior.zig | 1 + test/behavior/switch_on_captured_error.zig | 1 + 2 files changed, 2 insertions(+) diff --git a/test/behavior.zig b/test/behavior.zig index 3081f6c9f969..ea8ea713aca9 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -89,6 +89,7 @@ test { _ = @import("behavior/switch.zig"); _ = @import("behavior/switch_prong_err_enum.zig"); _ = @import("behavior/switch_prong_implicit_cast.zig"); + _ = @import("behavior/switch_on_captured_error.zig"); _ = @import("behavior/this.zig"); _ = @import("behavior/threadlocal.zig"); _ = @import("behavior/truncate.zig"); diff --git a/test/behavior/switch_on_captured_error.zig b/test/behavior/switch_on_captured_error.zig index f5ba762559fa..570b98874a93 100644 --- a/test/behavior/switch_on_captured_error.zig +++ b/test/behavior/switch_on_captured_error.zig @@ -3,6 +3,7 @@ const assert = std.debug.assert; const expect = std.testing.expect; const expectError = std.testing.expectError; const expectEqual = std.testing.expectEqual; +const builtin = @import("builtin"); test "switch on error union catch capture" { if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; From b43d21dc1a40a9a768d2b4495fb687acd6e85040 Mon Sep 17 00:00:00 2001 From: dweiller <4678790+dweiller@users.noreply.github.com> Date: Fri, 10 May 2024 13:16:48 +1000 Subject: [PATCH 3/4] test: disable failing err union switch tests on wasm --- test/behavior/switch_on_captured_error.zig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/behavior/switch_on_captured_error.zig b/test/behavior/switch_on_captured_error.zig index 570b98874a93..98e0c2dda940 100644 --- a/test/behavior/switch_on_captured_error.zig +++ b/test/behavior/switch_on_captured_error.zig @@ -7,6 +7,7 @@ const builtin = @import("builtin"); test "switch on error union catch capture" { if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; const S = struct { const Error = error{ A, B, C }; @@ -261,6 +262,7 @@ test "switch on error union catch capture" { test "switch on error union if else capture" { if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; const S = struct { const Error = error{ A, B, C }; From b264cc404a6dfe362bc59a2f7ae316a6fae15204 Mon Sep 17 00:00:00 2001 From: dweiller <4678790+dweiller@users.noreply.github.com> Date: Thu, 9 May 2024 03:56:09 +1000 Subject: [PATCH 4/4] test: add address of tests for error union switch --- test/behavior/switch_on_captured_error.zig | 79 ++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/test/behavior/switch_on_captured_error.zig b/test/behavior/switch_on_captured_error.zig index 98e0c2dda940..6e70c851b1fe 100644 --- a/test/behavior/switch_on_captured_error.zig +++ b/test/behavior/switch_on_captured_error.zig @@ -18,6 +18,7 @@ test "switch on error union catch capture" { try testCapture(); try testInline(); try testEmptyErrSet(); + try testAddressOf(); } fn testScalar() !void { @@ -254,6 +255,44 @@ test "switch on error union catch capture" { try expectEqual(@as(u64, 0), b); } } + + fn testAddressOf() !void { + { + const a: anyerror!usize = 0; + const ptr = &(a catch |e| switch (e) { + else => 3, + }); + comptime assert(@TypeOf(ptr) == *const usize); + try expectEqual(ptr, &(a catch unreachable)); + } + { + const a: anyerror!usize = error.A; + const ptr = &(a catch |e| switch (e) { + else => 3, + }); + comptime assert(@TypeOf(ptr) == *const comptime_int); + try expectEqual(3, ptr.*); + } + { + var a: anyerror!usize = 0; + _ = &a; + const ptr = &(a catch |e| switch (e) { + else => return, + }); + comptime assert(@TypeOf(ptr) == *usize); + ptr.* += 1; + try expectEqual(@as(usize, 1), a catch unreachable); + } + { + var a: anyerror!usize = error.A; + _ = &a; + const ptr = &(a catch |e| switch (e) { + else => return, + }); + comptime assert(@TypeOf(ptr) == *usize); + unreachable; + } + } }; try comptime S.doTheTest(); @@ -279,6 +318,7 @@ test "switch on error union if else capture" { try testInlinePtr(); try testEmptyErrSet(); try testEmptyErrSetPtr(); + try testAddressOf(); } fn testScalar() !void { @@ -750,6 +790,45 @@ test "switch on error union if else capture" { try expectEqual(@as(u64, 0), b); } } + + fn testAddressOf() !void { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; + { + const a: anyerror!usize = 0; + const ptr = &(if (a) |*v| v.* else |e| switch (e) { + else => 3, + }); + comptime assert(@TypeOf(ptr) == *const usize); + try expectEqual(ptr, &(a catch unreachable)); + } + { + const a: anyerror!usize = error.A; + const ptr = &(if (a) |*v| v.* else |e| switch (e) { + else => 3, + }); + comptime assert(@TypeOf(ptr) == *const comptime_int); + try expectEqual(3, ptr.*); + } + { + var a: anyerror!usize = 0; + _ = &a; + const ptr = &(if (a) |*v| v.* else |e| switch (e) { + else => return, + }); + comptime assert(@TypeOf(ptr) == *usize); + ptr.* += 1; + try expectEqual(@as(usize, 1), a catch unreachable); + } + { + var a: anyerror!usize = error.A; + _ = &a; + const ptr = &(if (a) |*v| v.* else |e| switch (e) { + else => return, + }); + comptime assert(@TypeOf(ptr) == *usize); + unreachable; + } + } }; try comptime S.doTheTest();