Skip to content

Commit 1a14429

Browse files
vtjnashKristofferC
authored andcommitted
restore method count after redefinition to hide old definition (#57837)
Purely on the external show, since the method does still exist for internals purposes (e.g. method deletion) and is already filtered for inference users (with lim > 0). Close #53814 (cherry picked from commit 35e2886)
1 parent a60a978 commit 1a14429

File tree

4 files changed

+29
-16
lines changed

4 files changed

+29
-16
lines changed

Compiler/test/invalidation.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,8 @@ begin
142142
# this redefinition below should invalidate the cache of `pr48932_callee` but not that of `pr48932_caller`
143143
pr48932_callee(x) = (print(GLOBAL_BUFFER, x); nothing)
144144

145-
@test length(Base.methods(pr48932_callee)) == 2
146-
@test Base.only(Base.methods(pr48932_callee, Tuple{Any})) === first(Base.methods(pr48932_callee))
145+
@test length(Base.methods(pr48932_callee)) == 1
146+
@test Base.only(Base.methods(pr48932_callee, Tuple{Any})) === only(Base.methods(pr48932_callee))
147147
@test isempty(Base.specializations(Base.only(Base.methods(pr48932_callee, Tuple{Any}))))
148148
let mi = only(Base.specializations(Base.only(Base.methods(pr48932_caller))))
149149
# Base.method_instance(pr48932_callee, (Any,))

base/runtime_internals.jl

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,31 +1321,44 @@ function MethodList(mt::Core.MethodTable)
13211321
return MethodList(ms, mt)
13221322
end
13231323

1324+
function matches_to_methods(ms::Array{Any,1}, mt::Core.MethodTable, mod)
1325+
# Lack of specialization => a comprehension triggers too many invalidations via _collect, so collect the methods manually
1326+
ms = Method[(ms[i]::Core.MethodMatch).method for i in 1:length(ms)]
1327+
# Remove shadowed methods with identical type signatures
1328+
prev = nothing
1329+
filter!(ms) do m
1330+
l = prev
1331+
repeated = (l isa Method && m.sig == l.sig)
1332+
prev = m
1333+
return !repeated
1334+
end
1335+
# Remove methods not part of module (after removing shadowed methods)
1336+
mod === nothing || filter!(ms) do m
1337+
return parentmodule(m) mod
1338+
end
1339+
return MethodList(ms, mt)
1340+
end
1341+
13241342
"""
13251343
methods(f, [types], [module])
13261344
13271345
Return the method table for `f`.
13281346
13291347
If `types` is specified, return an array of methods whose types match.
13301348
If `module` is specified, return an array of methods defined in that module.
1331-
A list of modules can also be specified as an array.
1349+
A list of modules can also be specified as an array or set.
13321350
13331351
!!! compat "Julia 1.4"
13341352
At least Julia 1.4 is required for specifying a module.
13351353
13361354
See also: [`which`](@ref), [`@which`](@ref Main.InteractiveUtils.@which) and [`methodswith`](@ref Main.InteractiveUtils.methodswith).
13371355
"""
13381356
function methods(@nospecialize(f), @nospecialize(t),
1339-
mod::Union{Tuple{Module},AbstractArray{Module},Nothing}=nothing)
1357+
mod::Union{Tuple{Module},AbstractArray{Module},AbstractSet{Module},Nothing}=nothing)
13401358
world = get_world_counter()
13411359
world == typemax(UInt) && error("code reflection cannot be used from generated functions")
1342-
# Lack of specialization => a comprehension triggers too many invalidations via _collect, so collect the methods manually
1343-
ms = Method[]
1344-
for m in _methods(f, t, -1, world)::Vector
1345-
m = m::Core.MethodMatch
1346-
(mod === nothing || parentmodule(m.method) mod) && push!(ms, m.method)
1347-
end
1348-
MethodList(ms, typeof(f).name.mt)
1360+
ms = _methods(f, t, -1, world)::Vector{Any}
1361+
return matches_to_methods(ms, typeof(f).name.mt, mod)
13491362
end
13501363
methods(@nospecialize(f), @nospecialize(t), mod::Module) = methods(f, t, (mod,))
13511364

@@ -1355,12 +1368,12 @@ function methods_including_ambiguous(@nospecialize(f), @nospecialize(t))
13551368
world == typemax(UInt) && error("code reflection cannot be used from generated functions")
13561369
min = RefValue{UInt}(typemin(UInt))
13571370
max = RefValue{UInt}(typemax(UInt))
1358-
ms = _methods_by_ftype(tt, nothing, -1, world, true, min, max, Ptr{Int32}(C_NULL))::Vector
1359-
return MethodList(Method[(m::Core.MethodMatch).method for m in ms], typeof(f).name.mt)
1371+
ms = _methods_by_ftype(tt, nothing, -1, world, true, min, max, Ptr{Int32}(C_NULL))::Vector{Any}
1372+
return matches_to_methods(ms, typeof(f).name.mt, nothing)
13601373
end
13611374

13621375
function methods(@nospecialize(f),
1363-
mod::Union{Module,AbstractArray{Module},Nothing}=nothing)
1376+
mod::Union{Module,AbstractArray{Module},AbstractSet{Module},Nothing}=nothing)
13641377
# return all matches
13651378
return methods(f, Tuple{Vararg{Any}}, mod)
13661379
end

test/core.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7691,7 +7691,7 @@ end
76917691
# issue #31696
76927692
foo31696(x::Int8, y::Int8) = 1
76937693
foo31696(x::T, y::T) where {T <: Int8} = 2
7694-
@test length(methods(foo31696)) == 2
7694+
@test length(methods(foo31696)) == 1
76957695
let T1 = Tuple{Int8}, T2 = Tuple{T} where T<:Int8, a = T1[(1,)], b = T2[(1,)]
76967696
b .= a
76977697
@test b[1] == (1,)

test/reflection.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ fLargeTable() = 4
569569
fLargeTable(::Union, ::Union) = "a"
570570
@test fLargeTable(Union{Int, Missing}, Union{Int, Missing}) == "a"
571571
fLargeTable(::Union, ::Union) = "b"
572-
@test length(methods(fLargeTable)) == 206
572+
@test length(methods(fLargeTable)) == 205
573573
@test fLargeTable(Union{Int, Missing}, Union{Int, Missing}) == "b"
574574

575575
# issue #15280

0 commit comments

Comments
 (0)