diff --git a/base/methodshow.jl b/base/methodshow.jl
index 1be14a73ec338..cf8e59de3a8b4 100644
--- a/base/methodshow.jl
+++ b/base/methodshow.jl
@@ -2,6 +2,14 @@
# Method and method table pretty-printing
+const empty_sym = Symbol("")
+function strip_gensym(sym)
+ if sym === Symbol("#self#") || sym === Symbol("#unused#")
+ return empty_sym
+ end
+ return Symbol(replace(String(sym), r"^(.*)#(.*#)?\d+$" => s"\1"))
+end
+
function argtype_decl(env, n, @nospecialize(sig::DataType), i::Int, nargs, isva::Bool) # -> (argname, argtype)
t = sig.parameters[i]
if i == nargs && isva && !isvarargtype(t)
@@ -10,13 +18,13 @@ function argtype_decl(env, n, @nospecialize(sig::DataType), i::Int, nargs, isva:
if isa(n,Expr)
n = n.args[1] # handle n::T in arg list
end
- s = string(n)::String
- i = findfirst(isequal('#'), s)
- if i !== nothing
- s = s[1:prevind(s, i)::Int]
- end
- if t === Any && !isempty(s)
- return s, ""
+ n = strip_gensym(n)
+ local s
+ if n === empty_sym
+ s = ""
+ else
+ s = sprint(show_sym, n)
+ t === Any && return s, ""
end
if isvarargtype(t)
v1, v2 = nothing, nothing
@@ -73,8 +81,6 @@ function arg_decl_parts(m::Method, html=false)
return tv, decls, file, line
end
-const empty_sym = Symbol("")
-
# NOTE: second argument is deprecated and is no longer used
function kwarg_decl(m::Method, kwtype = nothing)
mt = get_methodtable(m)
@@ -184,6 +190,15 @@ function functionloc(@nospecialize(f))
return functionloc(first(mt))
end
+function sym_to_string(sym)
+ s = String(sym)
+ if endswith(s, "...")
+ return string(sprint(show_sym, Symbol(s[1:end-3])), "...")
+ else
+ return sprint(show_sym, sym)
+ end
+end
+
function show(io::IO, m::Method)
tv, decls, file, line = arg_decl_parts(m)
sig = unwrap_unionall(m.sig)
@@ -193,12 +208,16 @@ function show(io::IO, m::Method)
return
end
print(io, decls[1][2], "(")
- join(io, String[isempty(d[2]) ? d[1] : d[1]*"::"*d[2] for d in decls[2:end]],
- ", ", ", ")
+ join(
+ io,
+ String[isempty(d[2]) ? d[1] : string(d[1], "::", d[2]) for d in decls[2:end]],
+ ", ",
+ ", ",
+ )
kwargs = kwarg_decl(m)
if !isempty(kwargs)
print(io, "; ")
- join(io, kwargs, ", ", ", ")
+ join(io, map(sym_to_string, kwargs), ", ", ", ")
end
print(io, ")")
show_method_params(io, tv)
@@ -339,12 +358,18 @@ function show(io::IO, ::MIME"text/html", m::Method)
return
end
print(io, decls[1][2], "(")
- join(io, String[isempty(d[2]) ? d[1] : d[1]*"::"*d[2]*""
- for d in decls[2:end]], ", ", ", ")
+ join(
+ io,
+ String[
+ isempty(d[2]) ? d[1] : string(d[1], "::", d[2], "") for d in decls[2:end]
+ ],
+ ", ",
+ ", ",
+ )
kwargs = kwarg_decl(m)
if !isempty(kwargs)
print(io, "; ")
- join(io, kwargs, ", ", ", ")
+ join(io, map(sym_to_string, kwargs), ", ", ", ")
print(io, "")
end
print(io, ")")
diff --git a/base/show.jl b/base/show.jl
index 1984a6349edea..b03ccf0f474e2 100644
--- a/base/show.jl
+++ b/base/show.jl
@@ -2028,7 +2028,7 @@ function show_signature_function(io::IO, @nospecialize(ft), demangle=false, farg
if ft <: Function && isa(uw, DataType) && isempty(uw.parameters) &&
isdefined(uw.name.module, uw.name.mt.name) &&
ft == typeof(getfield(uw.name.module, uw.name.mt.name))
- print(io, (demangle ? demangle_function_name : identity)(uw.name.mt.name))
+ show_sym(io, (demangle ? demangle_function_name : identity)(uw.name.mt.name))
elseif isa(ft, DataType) && ft.name === Type.body.name &&
(f = ft.parameters[1]; !isa(f, TypeVar))
uwf = unwrap_unionall(f)
diff --git a/test/errorshow.jl b/test/errorshow.jl
index 2d370d7f05246..047e34bad69f6 100644
--- a/test/errorshow.jl
+++ b/test/errorshow.jl
@@ -426,7 +426,7 @@ let err_str,
@test startswith(sprint(show, which(Complex{Int}, Tuple{Int})),
"Complex{T}(")
@test startswith(sprint(show, which(getfield(Base, Symbol("@doc")), Tuple{LineNumberNode, Module, Vararg{Any}})),
- "@doc(__source__::LineNumberNode, __module__::Module, x...) in Core at boot.jl:")
+ "var\"@doc\"(__source__::LineNumberNode, __module__::Module, x...) in Core at boot.jl:")
@test startswith(sprint(show, which(FunctionLike(), Tuple{})),
"(::$(curmod_prefix)FunctionLike)() in $curmod_str at $sp:$(method_defs_lineno + 7)")
@test startswith(sprint(show, which(StructWithUnionAllMethodDefs{<:Integer}, (Any,))),
diff --git a/test/show.jl b/test/show.jl
index f2cfc21a9578f..06012a76f38f8 100644
--- a/test/show.jl
+++ b/test/show.jl
@@ -2018,3 +2018,23 @@ end
@test Base.make_typealias(M37012.AStruct{1}) === nothing
@test isempty(Base.make_typealiases(M37012.AStruct{1})[1])
@test string(M37012.AStruct{1}) == "$(curmod_prefix)M37012.AStruct{1}"
+
+@testset "method printing with non-standard identifiers" for _show in (
+ show,
+ (io, x) -> show(io, MIME("text/html"), x),
+)
+ @eval var","(x) = x
+ @test occursin("var\",\"(x)", sprint(_show, methods(var",")))
+
+ @eval f1(var"a.b") = 3
+ @test occursin("f1(var\"a.b\")", sprint(_show, methods(f1)))
+
+ @eval f2(; var"123") = 5
+ @test occursin("f2(; var\"123\")", sprint(_show, methods(f2)))
+
+ @eval f3(; var"%!"...) = 7
+ @test occursin("f3(; var\"%!\"...)", sprint(_show, methods(f3)))
+
+ @eval f4(; var"...") = 9
+ @test_broken occursin("f4(; var\"...\")", sprint(_show, methods(f4)))
+end