From 1718b43e40af478441eedac8d7fb1d648dd0b2dc Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Sat, 17 Jan 2026 13:00:16 +0100 Subject: [PATCH] Backport 60718+60746: Fix and test `jl_method_lookup_by_tt` for custom method tables --- src/gf.c | 12 ++++++------ test/core.jl | 26 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/gf.c b/src/gf.c index 47db5474701ac..9dcca5637be09 100644 --- a/src/gf.c +++ b/src/gf.c @@ -1841,7 +1841,7 @@ JL_DLLEXPORT jl_typemap_entry_t *jl_mt_find_cache_entry(jl_methcache_t *mc JL_PR return entry; } -static jl_method_instance_t *jl_mt_assoc_by_type(jl_methcache_t *mc JL_PROPAGATES_ROOT, jl_datatype_t *tt JL_MAYBE_UNROOTED, size_t world) +static jl_method_instance_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_methcache_t *mc JL_PROPAGATES_ROOT, jl_datatype_t *tt JL_MAYBE_UNROOTED, size_t world) { jl_typemap_entry_t *entry = jl_mt_find_cache_entry(mc, tt, world); if (entry) @@ -1858,11 +1858,11 @@ static jl_method_instance_t *jl_mt_assoc_by_type(jl_methcache_t *mc JL_PROPAGATE if (!mi) { size_t min_valid = 0; size_t max_valid = ~(size_t)0; - matc = _gf_invoke_lookup((jl_value_t*)tt, jl_method_table, world, 0, &min_valid, &max_valid); + matc = _gf_invoke_lookup((jl_value_t*)tt, mt, world, 0, &min_valid, &max_valid); if (matc) { jl_method_t *m = matc->method; jl_svec_t *env = matc->sparams; - mi = cache_method(jl_method_table, mc, &mc->cache, (jl_value_t*)mc, tt, m, world, min_valid, max_valid, env); + mi = cache_method(mt, mc, &mc->cache, (jl_value_t*)mc, tt, m, world, min_valid, max_valid, env); JL_GC_POP(); return mi; } @@ -3079,7 +3079,7 @@ JL_DLLEXPORT jl_value_t *jl_method_lookup_by_tt(jl_tupletype_t *tt, size_t world mt = (jl_methtable_t*) _mt; } jl_methcache_t *mc = mt->cache; - jl_method_instance_t *mi = jl_mt_assoc_by_type(mc, tt, world); + jl_method_instance_t *mi = jl_mt_assoc_by_type(mt, mc, tt, world); if (!mi) return jl_nothing; return (jl_value_t*) mi; @@ -3094,7 +3094,7 @@ JL_DLLEXPORT jl_method_instance_t *jl_method_lookup(jl_value_t **args, size_t na if (entry) return entry->func.linfo; jl_tupletype_t *tt = arg_type_tuple(args[0], &args[1], nargs); - return jl_mt_assoc_by_type(mc, tt, world); + return jl_mt_assoc_by_type(jl_method_table, mc, tt, world); } // return a Vector{Any} of svecs, each describing a method match: @@ -4169,7 +4169,7 @@ STATIC_INLINE jl_method_instance_t *jl_lookup_generic_(jl_value_t *F, jl_value_t assert(tt); // cache miss case jl_methcache_t *mc = jl_method_table->cache; - mfunc = jl_mt_assoc_by_type(mc, tt, world); + mfunc = jl_mt_assoc_by_type(jl_method_table, mc, tt, world); if (jl_options.malloc_log) jl_gc_sync_total_bytes(last_alloc); // discard allocation count from compilation if (mfunc == NULL) { diff --git a/test/core.jl b/test/core.jl index d18f7fe8136b6..d85a4f3c2eb74 100644 --- a/test/core.jl +++ b/test/core.jl @@ -8422,6 +8422,32 @@ let ms = Base._methods_by_ftype(Tuple{typeof(sin), Int}, OverlayModule.mt, 1, Ba @test isempty(ms) end +# fresh module to ensure uncached methods +module OverlayMTTest + using Base.Experimental: @MethodTable, @overlay + @MethodTable(mt) + + function overlay_only end + @overlay mt overlay_only(x::Int) = x * 2 +end + +# #60702 & #60716: Overlay methods must be found without prior cache population +let world = Base.get_world_counter() + mi = Base.method_instance(OverlayMTTest.overlay_only, Tuple{Int}; + world, method_table=OverlayMTTest.mt) + @test mi isa Core.MethodInstance + @test mi.def.module === OverlayMTTest +end + +# #60712: Global-only methods must NOT be found via custom MT +let + @eval global_only_func(x::Int) = x + 1 + world = Base.get_world_counter() + mi = Base.method_instance(global_only_func, Tuple{Int}; + world, method_table=OverlayMTTest.mt) + @test mi === nothing +end + # precompilation let load_path = mktempdir() depot_path = mkdepottempdir()