Skip to content

Commit 40bc64c

Browse files
ararslanvtjnash
andauthored
Fix show for MethodList when methods are from another module (#52354)
When a type is defined in one module but its methods are defined elsewhere, `show_method_table` errors due to an incorrect lookup of the defining module used to determine colors for printing. In particular, the code had been assuming that the type is defined in the module in which its constructor's first method (in the sense of `first(methods())`) is defined, which isn't always true. The color used for printing the module name needs to be determined on a per-method basis and can't be correctly done based on the method table's module. For each method, we attempt to derive the module for the method table to which the method was added, then determine whether it's the same as the defining module for the method. Fixes #49382 Fixes #49403 Fixes #52043 Co-Authored-By: Jameson Nash <vtjnash@gmail.com>
1 parent 9443c76 commit 40bc64c

File tree

3 files changed

+36
-14
lines changed

3 files changed

+36
-14
lines changed

base/methodshow.jl

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,29 @@ function show_method_list_header(io::IO, ms::MethodList, namefmt::Function)
286286
!iszero(n) && print(io, ":")
287287
end
288288

289+
# Determine the `modulecolor` value to pass to `show_method`
290+
function _modulecolor(method::Method)
291+
mmt = get_methodtable(method)
292+
if mmt === nothing || mmt.module === parentmodule(method)
293+
return nothing
294+
end
295+
# `mmt` is only particularly relevant for external method tables. Since the primary
296+
# method table is shared, we now need to distinguish "primary" methods by trying to
297+
# check if there is a primary `DataType` to identify it with. c.f. how `jl_method_def`
298+
# would derive this same information (for the name).
299+
ft = argument_datatype((unwrap_unionall(method.sig)::DataType).parameters[1])
300+
# `ft` should be the type associated with the first argument in the method signature.
301+
# If it's `Type`, try to unwrap it again.
302+
if isType(ft)
303+
ft = argument_datatype(ft.parameters[1])
304+
end
305+
if ft === nothing || parentmodule(method) === parentmodule(ft) !== Core
306+
return nothing
307+
end
308+
m = parentmodule_before_main(method)
309+
return get!(() -> popfirst!(STACKTRACE_MODULECOLORS), STACKTRACE_FIXEDCOLORS, m)
310+
end
311+
289312
function show_method_table(io::IO, ms::MethodList, max::Int=-1, header::Bool=true)
290313
mt = ms.mt
291314
name = mt.name
@@ -300,12 +323,6 @@ function show_method_table(io::IO, ms::MethodList, max::Int=-1, header::Bool=tru
300323
last_shown_line_infos = get(io, :last_shown_line_infos, nothing)
301324
last_shown_line_infos === nothing || empty!(last_shown_line_infos)
302325

303-
modul = if mt === _TYPE_NAME.mt && length(ms) > 0 # type constructor
304-
which(ms.ms[1].module, ms.ms[1].name)
305-
else
306-
mt.module
307-
end
308-
309326
digit_align_width = length(string(max > 0 ? max : length(ms)))
310327

311328
for meth in ms
@@ -315,13 +332,7 @@ function show_method_table(io::IO, ms::MethodList, max::Int=-1, header::Bool=tru
315332

316333
print(io, " ", lpad("[$n]", digit_align_width + 2), " ")
317334

318-
modulecolor = if parentmodule(meth) == modul
319-
nothing
320-
else
321-
m = parentmodule_before_main(meth)
322-
get!(() -> popfirst!(STACKTRACE_MODULECOLORS), STACKTRACE_FIXEDCOLORS, m)
323-
end
324-
show_method(io, meth; modulecolor)
335+
show_method(io, meth; modulecolor=_modulecolor(meth))
325336

326337
file, line = updated_methodloc(meth)
327338
if last_shown_line_infos !== nothing

base/reflection.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2507,7 +2507,11 @@ function delete_method(m::Method)
25072507
end
25082508

25092509
function get_methodtable(m::Method)
2510-
return ccall(:jl_method_get_table, Any, (Any,), m)::Core.MethodTable
2510+
mt = ccall(:jl_method_get_table, Any, (Any,), m)
2511+
if mt === nothing
2512+
return nothing
2513+
end
2514+
return mt::Core.MethodTable
25112515
end
25122516

25132517
"""

test/show.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2652,3 +2652,10 @@ let buf = IOBuffer()
26522652
Base.show_tuple_as_call(buf, Symbol(""), Tuple{Function,Any})
26532653
@test String(take!(buf)) == "(::Function)(::Any)"
26542654
end
2655+
2656+
module Issue49382
2657+
abstract type Type49382 end
2658+
end
2659+
using .Issue49382
2660+
(::Type{Issue49382.Type49382})() = 1
2661+
@test sprint(show, methods(Issue49382.Type49382)) isa String

0 commit comments

Comments
 (0)