diff --git a/base/methodshow.jl b/base/methodshow.jl index 0eb99dc88303f..477acd2960c48 100644 --- a/base/methodshow.jl +++ b/base/methodshow.jl @@ -286,6 +286,29 @@ function show_method_list_header(io::IO, ms::MethodList, namefmt::Function) !iszero(n) && print(io, ":") end +# Determine the `modulecolor` value to pass to `show_method` +function _modulecolor(method::Method) + mmt = get_methodtable(method) + if mmt === nothing || mmt.module === parentmodule(method) + return nothing + end + # `mmt` is only particularly relevant for external method tables. Since the primary + # method table is shared, we now need to distinguish "primary" methods by trying to + # check if there is a primary `DataType` to identify it with. c.f. how `jl_method_def` + # would derive this same information (for the name). + ft = argument_datatype((unwrap_unionall(method.sig)::DataType).parameters[1]) + # `ft` should be the type associated with the first argument in the method signature. + # If it's `Type`, try to unwrap it again. + if isType(ft) + ft = argument_datatype(ft.parameters[1]) + end + if ft === nothing || parentmodule(method) === parentmodule(ft) !== Core + return nothing + end + m = parentmodule_before_main(method) + return get!(() -> popfirst!(STACKTRACE_MODULECOLORS), STACKTRACE_FIXEDCOLORS, m) +end + function show_method_table(io::IO, ms::MethodList, max::Int=-1, header::Bool=true) mt = ms.mt name = mt.name @@ -300,12 +323,6 @@ function show_method_table(io::IO, ms::MethodList, max::Int=-1, header::Bool=tru last_shown_line_infos = get(io, :last_shown_line_infos, nothing) last_shown_line_infos === nothing || empty!(last_shown_line_infos) - modul = if mt === _TYPE_NAME.mt && length(ms) > 0 # type constructor - which(ms.ms[1].module, ms.ms[1].name) - else - mt.module - end - digit_align_width = length(string(max > 0 ? max : length(ms))) for meth in ms @@ -315,13 +332,7 @@ function show_method_table(io::IO, ms::MethodList, max::Int=-1, header::Bool=tru print(io, " ", lpad("[$n]", digit_align_width + 2), " ") - modulecolor = if parentmodule(meth) == modul - nothing - else - m = parentmodule_before_main(meth) - get!(() -> popfirst!(STACKTRACE_MODULECOLORS), STACKTRACE_FIXEDCOLORS, m) - end - show_method(io, meth; modulecolor) + show_method(io, meth; modulecolor=_modulecolor(meth)) file, line = updated_methodloc(meth) if last_shown_line_infos !== nothing diff --git a/base/reflection.jl b/base/reflection.jl index adbd20deab636..306f21cbc5f23 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -2507,7 +2507,11 @@ function delete_method(m::Method) end function get_methodtable(m::Method) - return ccall(:jl_method_get_table, Any, (Any,), m)::Core.MethodTable + mt = ccall(:jl_method_get_table, Any, (Any,), m) + if mt === nothing + return nothing + end + return mt::Core.MethodTable end """ diff --git a/test/show.jl b/test/show.jl index a2ed2bba31f50..08a29612b245c 100644 --- a/test/show.jl +++ b/test/show.jl @@ -2652,3 +2652,10 @@ let buf = IOBuffer() Base.show_tuple_as_call(buf, Symbol(""), Tuple{Function,Any}) @test String(take!(buf)) == "(::Function)(::Any)" end + +module Issue49382 + abstract type Type49382 end +end +using .Issue49382 +(::Type{Issue49382.Type49382})() = 1 +@test sprint(show, methods(Issue49382.Type49382)) isa String