Skip to content

Commit a43b3ad

Browse files
committed
In errorshow UI, filter out frames for _include implementation
This simplifies stack traces for include() which were made much more complex by moving jl_parse_eval_all to the Julia layer.
1 parent bd0525c commit a43b3ad

File tree

4 files changed

+66
-11
lines changed

4 files changed

+66
-11
lines changed

base/errorshow.jl

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,42 @@ function is_kw_sorter_name(name::Symbol)
681681
return !startswith(sn, '#') && endswith(sn, "##kw")
682682
end
683683

684+
# For improved user experience, filter out frames for include() implementation
685+
# - see #33065. See also #35371 for extended discussion of internal frames.
686+
function _simplify_include_frames(trace)
687+
kept_frames = trues(length(trace))
688+
i = length(trace)
689+
first_ignored = nothing
690+
while i >= 1
691+
frame,_ = trace[i]
692+
mod = parentmodule(frame)
693+
if isnothing(first_ignored)
694+
if mod === Base && frame.func === :_include
695+
# Hide include() machinery by default
696+
first_ignored = i
697+
end
698+
else
699+
# Hack: allow `mod==nothing` as a workaround for inlined functions.
700+
# TODO: Fix this by improving debug info.
701+
if mod in (Base,Core,nothing) && 1+first_ignored-i <= 5
702+
if frame.func == :eval
703+
@debug "Ignoring frames" removed=trace[i:first_ignored]
704+
kept_frames[i:first_ignored] .= false
705+
first_ignored = nothing
706+
end
707+
else
708+
# Bail out to avoid hiding frames in unexpected circumstances
709+
first_ignored = nothing
710+
end
711+
end
712+
i -= 1
713+
end
714+
if !isnothing(first_ignored)
715+
kept_frames[i:first_ignored] .= false
716+
end
717+
trace[kept_frames]
718+
end
719+
684720
function process_backtrace(t::Vector, limit::Int=typemax(Int); skipC = true)
685721
n = 0
686722
last_frame = StackTraces.UNKNOWN
@@ -721,7 +757,7 @@ function process_backtrace(t::Vector, limit::Int=typemax(Int); skipC = true)
721757
if n > 0
722758
push!(ret, (last_frame, n))
723759
end
724-
return ret
760+
return _simplify_include_frames(ret)
725761
end
726762

727763
function show_exception_stack(io::IO, stack::Vector)

base/stacktraces.jl

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -268,22 +268,29 @@ function show(io::IO, frame::StackFrame; full_path::Bool=false)
268268
end
269269
end
270270

271+
function Base.parentmodule(frame::StackFrame)
272+
if frame.linfo isa MethodInstance
273+
def = frame.linfo.def
274+
if def isa Module
275+
return def
276+
else
277+
@assert def isa Method
278+
return def.module
279+
end
280+
else
281+
# Bug: currently the module is not available for inlined frames and
282+
# frames arising from the interpreter.
283+
nothing
284+
end
285+
end
286+
271287
"""
272288
from(frame::StackFrame, filter_mod::Module) -> Bool
273289
274290
Returns whether the `frame` is from the provided `Module`
275291
"""
276292
function from(frame::StackFrame, m::Module)
277-
finfo = frame.linfo
278-
result = false
279-
280-
if finfo isa MethodInstance
281-
frame_m = finfo.def
282-
isa(frame_m, Method) && (frame_m = frame_m.module)
283-
result = nameof(frame_m) === nameof(m)
284-
end
285-
286-
return result
293+
parentmodule(frame) == m
287294
end
288295

289296
end

test/errorshow.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,3 +704,14 @@ for (func,str) in ((TestMethodShadow.:+,":+"), (TestMethodShadow.:(==),":(==)"),
704704
end::MethodError
705705
@test occursin("You may have intended to import Base.$str", sprint(Base.showerror, ex))
706706
end
707+
708+
# Test that implementation detail of include() is hidden from the user by default
709+
let bt = try
710+
include("testhelpers/include_error.jl")
711+
catch
712+
catch_backtrace()
713+
end
714+
bt_str = sprint(Base.show_backtrace, bt)
715+
@test occursin(" include(", bt_str)
716+
@test !occursin(" _include(", bt_str)
717+
end

test/testhelpers/include_error.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
error("Expected exception while running include")

0 commit comments

Comments
 (0)