authorgravatar for nuno.pinto@live.comestevesnp <nuno.pinto@live.com> 2026-02-25 16:14:44+00:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-02-26 20:49:05+01:00
log0b6b65b387cdb145440a33922ab6c3fd10e6071f
treee246b4843332f13d7fa6581a5a9dd8ffef2ca3b6
parent2d867223be4139ac55b1be1f5c19eee8a393c62a

fix: Allow async and concurrent from Io.Select to accept non-void error unions


2 files changed, 18 insertions(+), 2 deletions(-)

lib/std/Io.zig+2-2
...@@ -1238,7 +1238,7 @@ pub fn Select(comptime U: type) type {...@@ -1238,7 +1238,7 @@ pub fn Select(comptime U: type) type {
1238 error.Closed => unreachable,1238 error.Closed => unreachable,
1239 };1239 };
1240 if (@typeInfo(@TypeOf(raw_result)) == .error_union)1240 if (@typeInfo(@TypeOf(raw_result)) == .error_union)
1241 raw_result catch |err| if (err == error.Canceled) return error.Canceled;1241 _ = raw_result catch |err| if (err == error.Canceled) return error.Canceled;
1242 }1242 }
1243 };1243 };
1244 const context: Context = .{ .select = s, .args = args };1244 const context: Context = .{ .select = s, .args = args };
...@@ -1277,7 +1277,7 @@ pub fn Select(comptime U: type) type {...@@ -1277,7 +1277,7 @@ pub fn Select(comptime U: type) type {
1277 error.Closed => unreachable,1277 error.Closed => unreachable,
1278 };1278 };
1279 if (@typeInfo(@TypeOf(raw_result)) == .error_union)1279 if (@typeInfo(@TypeOf(raw_result)) == .error_union)
1280 raw_result catch |err| if (err == error.Canceled) return error.Canceled;1280 _ = raw_result catch |err| if (err == error.Canceled) return error.Canceled;
1281 }1281 }
1282 };1282 };
1283 const context: Context = .{ .select = s, .args = args };1283 const context: Context = .{ .select = s, .args = args };
lib/std/Io/test.zig+16
...@@ -820,6 +820,10 @@ test "Select" {...@@ -820,6 +820,10 @@ test "Select" {
820 fn bar(io: Io) Io.Cancelable!void {820 fn bar(io: Io) Io.Cancelable!void {
821 try io.sleep(.fromSeconds(300), .awake);821 try io.sleep(.fromSeconds(300), .awake);
822 }822 }
823
824 fn baz() error{Ignored}!u8 {
825 return 42;
826 }
823 };827 };
824828
825 const io = testing.io;829 const io = testing.io;
...@@ -827,6 +831,7 @@ test "Select" {...@@ -827,6 +831,7 @@ test "Select" {
827 const U = union(enum) {831 const U = union(enum) {
828 foo: bool,832 foo: bool,
829 bar: Io.Cancelable!void,833 bar: Io.Cancelable!void,
834 baz: error{Ignored}!u8,
830 };835 };
831 var buffer: [4]U = undefined;836 var buffer: [4]U = undefined;
832 var select: Io.Select(U) = .init(io, &buffer);837 var select: Io.Select(U) = .init(io, &buffer);
...@@ -840,6 +845,7 @@ test "Select" {...@@ -840,6 +845,7 @@ test "Select" {
840 switch (try select.await()) {845 switch (try select.await()) {
841 .foo => {},846 .foo => {},
842 .bar => return error.TestFailed, // should be sleeping847 .bar => return error.TestFailed, // should be sleeping
848 .baz => return error.TestFailed, // not called yet
843 }849 }
844 select.async(.foo, S.foo, .{});850 select.async(.foo, S.foo, .{});
845 select.async(.foo, S.foo, .{});851 select.async(.foo, S.foo, .{});
...@@ -847,4 +853,14 @@ test "Select" {...@@ -847,4 +853,14 @@ test "Select" {
847 var finished_buffer: [3]U = undefined;853 var finished_buffer: [3]U = undefined;
848 const finished = finished_buffer[0..try select.awaitMany(&finished_buffer, 2)];854 const finished = finished_buffer[0..try select.awaitMany(&finished_buffer, 2)];
849 try testing.expectEqualSlices(U, &.{ .{ .foo = true }, .{ .foo = true } }, finished);855 try testing.expectEqualSlices(U, &.{ .{ .foo = true }, .{ .foo = true } }, finished);
856
857 select.async(.baz, S.baz, .{});
858
859 const result = switch (try select.await()) {
860 .baz => |n| try n,
861 .foo => return error.TestFailed, // not called
862 .bar => return error.TestFailed, // should be sleeping
863 };
864
865 try testing.expectEqual(42, result);
850}866}