From 9b5851f0019c6cf2b5a54ffa54acd7f13b941a07 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Thu, 25 Jun 2026 17:55:22 -0400 Subject: [PATCH] InternPool: fix incorrect coercion of `func_coerced` When trying to coerce a `func_coerced` value to another type, `getCoerced` checks the tag but passes the whole `func_coerced` value instead of the `func_decl` or `func_instance` which eventually leads to a panic in `extraFuncCoerced`. Instead, we should pass the uncoerced value to be coerced again. Closes https://github.com/ziglang/zig/issues/23235 --- src/InternPool.zig | 4 ++-- test/behavior/cast.zig | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/InternPool.zig b/src/InternPool.zig index be6e45441e55ec373e533643786528d0abeb310c..fc4c4ebec11646d461ebc585cb7fcaa85e99371e 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -10165,8 +10165,8 @@ pub fn getCoerced( val_item.data + std.meta.fieldIndex(Tag.FuncCoerced, "func").? ]); switch (func.unwrap(ip).getTag(ip)) { - .func_decl => return getCoercedFuncDecl(ip, gpa, io, tid, val, new_ty), - .func_instance => return getCoercedFuncInstance(ip, gpa, io, tid, val, new_ty), + .func_decl => return getCoercedFuncDecl(ip, gpa, io, tid, func, new_ty), + .func_instance => return getCoercedFuncInstance(ip, gpa, io, tid, func, new_ty), else => unreachable, } }, diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 41b53fdbbb0f17e9f27264eeaebcf4e376a68cfc..178c95de4037cc415d0caefd89e35baed3455cb8 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -3153,3 +3153,19 @@ test "coerce enum to union with zero-bit fields through local variables" { try expect(result == .foo); } + +test "coercing a coerced function" { + const S = struct { + fn doTheTest() !void { + const bar: fn (anytype, anytype) void = foo; + higherOrder(1, bar); + } + + fn foo(_: anytype, _: void) void {} + + fn higherOrder(x: anytype, f: fn (@TypeOf(x), void) void) void { + _ = f(x, {}); + } + }; + try S.doTheTest(); +} -- 2.54.0