Skip to content

Commit e8667fb

Browse files
authored
Avoid method instance normalization for opaque closure methods (#59772)
Fixes #59222. This issue was caused by a mismatch with `jl_new_opaque_closure_from_code_info_in_world` filling in the unnormalized method instance, and `new_opaque_closure` getting its `spec_ptr` from the normalized one via `jl_compile_method_internal`. For example, `g(xs...)` specialized as `g(:a, :b)` resulted in a different method instance than the corresponding normalized one: ```julia Tuple{Tuple{typeof(Main.g)}, Symbol, Symbol} # unnormalized Tuple{Tuple{typeof(Main.g)}, Symbol, Vararg{Symbol}} # normalized ``` Here I chose to align on using the unnormalized one from the `CodeInfo` at `OpaqueClosure` construction (the fix being a single-line change in that case), but we could also choose the normalized one if that is deemed preferable, so long as we use the same when storing the inferred code and when retrieving the `spec_ptr`. --- 🤖 Generated with some assistance from Claude Code.
1 parent 1cba9c2 commit e8667fb

File tree

2 files changed

+15
-1
lines changed

2 files changed

+15
-1
lines changed

src/gf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3809,7 +3809,7 @@ JL_DLLEXPORT jl_value_t *jl_normalize_to_compilable_sig(jl_tupletype_t *ti, jl_s
38093809
jl_method_instance_t *jl_normalize_to_compilable_mi(jl_method_instance_t *mi JL_PROPAGATES_ROOT)
38103810
{
38113811
jl_method_t *def = mi->def.method;
3812-
if (!jl_is_method(def) || !jl_is_datatype(mi->specTypes))
3812+
if (!jl_is_method(def) || !jl_is_datatype(mi->specTypes) || def->is_for_opaque_closure)
38133813
return mi;
38143814
jl_value_t *compilationsig = jl_normalize_to_compilable_sig((jl_datatype_t*)mi->specTypes, mi->sparam_vals, def, 1);
38153815
if (compilationsig == jl_nothing || jl_egal(compilationsig, mi->specTypes))

test/opaque_closure.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,20 @@ let src = code_typed((Int,Int)) do x, y...
297297
@test oc(1,2) === (1,(2,))
298298
@test_throws MethodError oc(1,2,3)
299299
end
300+
301+
# with manually constructed IRCode, without round-trip to CodeInfo
302+
f59222(xs...) = length(xs)
303+
ir = Base.code_ircode_by_type(Tuple{typeof(f59222), Symbol, Symbol})[1][1]
304+
ir.argtypes[1] = Tuple{}
305+
let oc = OpaqueClosure(ir; isva=true)
306+
@test oc(:a, :b) == 2
307+
end
308+
ir = Base.code_ircode_by_type(Tuple{typeof(f59222), Symbol, Vararg{Symbol}})[1][1]
309+
ir.argtypes[1] = Tuple{}
310+
let oc = OpaqueClosure(ir; isva=true)
311+
@test oc(:a) == 1
312+
@test oc(:a, :b, :c) == 3
313+
end
300314
end
301315

302316
# Check for correct handling in case of broken return type.

0 commit comments

Comments
 (0)