Skip to content

Commit fb4e890

Browse files
serenity4KristofferC
authored andcommitted
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. (cherry picked from commit e8667fb)
1 parent ae6d287 commit fb4e890

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
@@ -3683,7 +3683,7 @@ JL_DLLEXPORT jl_value_t *jl_normalize_to_compilable_sig(jl_tupletype_t *ti, jl_s
36833683
jl_method_instance_t *jl_normalize_to_compilable_mi(jl_method_instance_t *mi JL_PROPAGATES_ROOT)
36843684
{
36853685
jl_method_t *def = mi->def.method;
3686-
if (!jl_is_method(def) || !jl_is_datatype(mi->specTypes))
3686+
if (!jl_is_method(def) || !jl_is_datatype(mi->specTypes) || def->is_for_opaque_closure)
36873687
return mi;
36883688
jl_value_t *compilationsig = jl_normalize_to_compilable_sig((jl_datatype_t*)mi->specTypes, mi->sparam_vals, def, 1);
36893689
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)