From 5611779f391c9ae48c0abf7662b1e9020be6ea14 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sat, 20 Dec 2025 19:03:22 +0000 Subject: [PATCH] Sema: fix nested error union coercions Previously, `E1!void` failed to coerce to `E2!E1!void` because it tried to coerce the `E1` error to an `E2` if comptime-known and refused to attempt any other coercion. This is a strange language rule with no clear justification, and breaks real use cases (such as calling `getOne` on an `Io.Queue(E!T)`). Instead, only error *sets* should try to coerce to an "error" value of an error union type. --- src/Sema.zig | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 027e1eaac5..baeb9a62de 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -29023,33 +29023,6 @@ fn coerceExtra( else => {}, }, .error_union => switch (inst_ty.zigTypeTag(zcu)) { - .error_union => eu: { - if (maybe_inst_val) |inst_val| { - switch (inst_val.toIntern()) { - .undef => return pt.undefRef(dest_ty), - else => switch (zcu.intern_pool.indexToKey(inst_val.toIntern())) { - .error_union => |error_union| switch (error_union.val) { - .err_name => |err_name| { - const error_set_ty = inst_ty.errorUnionSet(zcu); - const error_set_val = Air.internedToRef((try pt.intern(.{ .err = .{ - .ty = error_set_ty.toIntern(), - .name = err_name, - } }))); - return sema.wrapErrorUnionSet(block, dest_ty, error_set_val, inst_src); - }, - .payload => |payload| { - const payload_val = Air.internedToRef(payload); - return sema.wrapErrorUnionPayload(block, dest_ty, payload_val, inst_src) catch |err| switch (err) { - error.NotCoercible => break :eu, - else => |e| return e, - }; - }, - }, - else => unreachable, - }, - } - } - }, .error_set => { // E to E!T return sema.wrapErrorUnionSet(block, dest_ty, inst, inst_src);