Skip to content

Commit

Permalink
Limit type-printing in MethodError (#50809)
Browse files Browse the repository at this point in the history
This applies the same `...` depth-based parametric truncation to
the signature in `MethodError` that we use in printing stacktraces.

Fixes #50803
  • Loading branch information
timholy committed Aug 16, 2023
1 parent 883c19b commit 90b4eed
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 13 deletions.
4 changes: 2 additions & 2 deletions base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ scrub_repl_backtrace(stack::ExceptionStack) =
ExceptionStack(Any[(;x.exception, backtrace = scrub_repl_backtrace(x.backtrace)) for x in stack])

istrivialerror(stack::ExceptionStack) =
length(stack) == 1 && length(stack[1].backtrace) 1
# frame 1 = top level; assumes already went through scrub_repl_backtrace
length(stack) == 1 && length(stack[1].backtrace) 1 && !isa(stack[1].exception, MethodError)
# frame 1 = top level; assumes already went through scrub_repl_backtrace; MethodError see #50803

function display_error(io::IO, stack::ExceptionStack)
printstyled(io, "ERROR: "; bold=true, color=Base.error_color())
Expand Down
20 changes: 12 additions & 8 deletions base/errorshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -268,20 +268,24 @@ function showerror(io::IO, ex::MethodError)
f_is_function = true
end
print(io, "no method matching ")
show_signature_function(io, isa(f, Type) ? Type{f} : typeof(f))
print(io, "(")
iob = IOContext(IOBuffer(), io) # for type abbreviation as in #49795; some, like `convert(T, x)`, should not abbreviate
show_signature_function(iob, isa(f, Type) ? Type{f} : typeof(f))
print(iob, "(")
for (i, typ) in enumerate(arg_types_param)
print(io, "::", typ)
i == length(arg_types_param) || print(io, ", ")
print(iob, "::", typ)
i == length(arg_types_param) || print(iob, ", ")
end
if !isempty(kwargs)
print(io, "; ")
print(iob, "; ")
for (i, (k, v)) in enumerate(kwargs)
print(io, k, "::", typeof(v))
i == length(kwargs)::Int || print(io, ", ")
print(iob, k, "::", typeof(v))
i == length(kwargs)::Int || print(iob, ", ")
end
end
print(io, ")")
print(iob, ")")
str = String(take!(unwrapcontext(iob)[1]))
str = type_limited_string_from_context(io, str)
print(io, str)
end
# catch the two common cases of element-wise addition and subtraction
if (f === Base.:+ || f === Base.:-) && length(arg_types_param) == 2
Expand Down
11 changes: 8 additions & 3 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2559,17 +2559,22 @@ function show_tuple_as_call(out::IO, name::Symbol, sig::Type;
print_within_stacktrace(io, ")", bold=true)
show_method_params(io, tv)
str = String(take!(unwrapcontext(io)[1]))
str = type_limited_string_from_context(out, str)
print(out, str)
nothing
end

function type_limited_string_from_context(out::IO, str::String)
typelimitflag = get(out, :stacktrace_types_limited, nothing)
if typelimitflag isa RefValue{Bool}
sz = get(out, :displaysize, (typemax(Int), typemax(Int)))::Tuple{Int, Int}
sz = get(out, :displaysize, displaysize(out))::Tuple{Int, Int}
str_lim = type_depth_limit(str, max(sz[2], 120))
if sizeof(str_lim) < sizeof(str)
typelimitflag[] = true
end
str = str_lim
end
print(out, str)
nothing
return str
end

# limit nesting depth of `{ }` until string textwidth is less than `n`
Expand Down
19 changes: 19 additions & 0 deletions test/errorshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,25 @@ foo_9965(x::Int) = 2x
@test occursin("got unsupported keyword argument \"w\"", String(take!(io)))
end

@testset "MethodError with long types (#50803)" begin
a = view(reinterpret(reshape, UInt8, PermutedDimsArray(rand(5, 7), (2, 1))), 2:3, 2:4, 1:4) # a mildly-complex type
function f50803 end
ex50803 = try
f50803(a, a, a, a, a, a)
catch e
e
end::MethodError
tlf = Ref(false)
str = sprint(Base.showerror, ex50803; context=(:displaysize=>(1000, 120), :stacktrace_types_limited=>tlf))
@test tlf[]
@test occursin("::SubArray{…}", str)
tlf[] = false
str = sprint(Base.showerror, ex50803; context=(:displaysize=>(1000, 10000), :stacktrace_types_limited=>tlf))
@test !tlf[]
str = sprint(Base.showerror, ex50803; context=(:displaysize=>(1000, 120)))
@test !occursin("::SubArray{…}", str)
end

# Issue #20556
import REPL
module EnclosingModule
Expand Down

3 comments on commit 90b4eed

@vtjnash
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nanosoldier runbenchmarks(ALL, isdaily = true)

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here.

@vtjnash
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inference did very well in this run, which I guess might have been due to 750df9f

Please sign in to comment.