From f88cb0b4c172b30602f7d645210e08392b50fb6f Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Fri, 4 Aug 2023 16:28:55 -0500 Subject: [PATCH 1/4] Limit type-printing in MethodError Fixes #50803 --- base/client.jl | 4 ++-- base/errorshow.jl | 24 ++++++++++++++++-------- base/show.jl | 9 +++++++-- test/errorshow.jl | 19 +++++++++++++++++++ 4 files changed, 44 insertions(+), 12 deletions(-) diff --git a/base/client.jl b/base/client.jl index 4ae345b14f113..247c102894688 100644 --- a/base/client.jl +++ b/base/client.jl @@ -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()) diff --git a/base/errorshow.jl b/base/errorshow.jl index 2a02747dc2a2b..660447d533360 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -268,20 +268,28 @@ 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])) + ioc = IOContext(io) + if !haskey(ioc, :displaysize) + ioc = IOContext(ioc, :displaysize => displaysize(io)) + end + str = type_limited_string_from_context(ioc, 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 diff --git a/base/show.jl b/base/show.jl index a980b7a7d8095..3a0d1c73efcce 100644 --- a/base/show.jl +++ b/base/show.jl @@ -2559,6 +2559,12 @@ 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} @@ -2568,8 +2574,7 @@ function show_tuple_as_call(out::IO, name::Symbol, sig::Type; end str = str_lim end - print(out, str) - nothing + return str end # limit nesting depth of `{ }` until string textwidth is less than `n` diff --git a/test/errorshow.jl b/test/errorshow.jl index 28ae3fd32365a..861d7dd0d68e3 100644 --- a/test/errorshow.jl +++ b/test/errorshow.jl @@ -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 From 8f31ab085eab6c4bc4397d591d343adfd999aad1 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Fri, 11 Aug 2023 23:27:24 -0500 Subject: [PATCH 2/4] Address review comment --- base/errorshow.jl | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/base/errorshow.jl b/base/errorshow.jl index 660447d533360..1538bc2b5e4f3 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -284,10 +284,7 @@ function showerror(io::IO, ex::MethodError) end print(iob, ")") str = String(take!(unwrapcontext(iob)[1])) - ioc = IOContext(io) - if !haskey(ioc, :displaysize) - ioc = IOContext(ioc, :displaysize => displaysize(io)) - end + ioc = !haskey(ioc, :displaysize) ? IOContext(io, :displaysize => displaysize(io)) : io str = type_limited_string_from_context(ioc, str) print(io, str) end From c8104a5719eec64d01b1ac8975e2227f3df9cc58 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sat, 12 Aug 2023 06:58:10 -0500 Subject: [PATCH 3/4] fix typo --- base/errorshow.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/errorshow.jl b/base/errorshow.jl index 1538bc2b5e4f3..93d7b9cb8dc86 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -284,7 +284,7 @@ function showerror(io::IO, ex::MethodError) end print(iob, ")") str = String(take!(unwrapcontext(iob)[1])) - ioc = !haskey(ioc, :displaysize) ? IOContext(io, :displaysize => displaysize(io)) : io + ioc = !haskey(io, :displaysize) ? IOContext(io, :displaysize => displaysize(io)) : io str = type_limited_string_from_context(ioc, str) print(io, str) end From 210ee4cbc48653f4eacc689ca0b504e94012386b Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Tue, 15 Aug 2023 05:08:16 -0500 Subject: [PATCH 4/4] Default to displaysize, not typemax --- base/errorshow.jl | 3 +-- base/show.jl | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/base/errorshow.jl b/base/errorshow.jl index 93d7b9cb8dc86..dd199f808e7ad 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -284,8 +284,7 @@ function showerror(io::IO, ex::MethodError) end print(iob, ")") str = String(take!(unwrapcontext(iob)[1])) - ioc = !haskey(io, :displaysize) ? IOContext(io, :displaysize => displaysize(io)) : io - str = type_limited_string_from_context(ioc, str) + str = type_limited_string_from_context(io, str) print(io, str) end # catch the two common cases of element-wise addition and subtraction diff --git a/base/show.jl b/base/show.jl index 3a0d1c73efcce..f5afa56481c56 100644 --- a/base/show.jl +++ b/base/show.jl @@ -2567,7 +2567,7 @@ 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