Skip to content

Adjust print_response to separate error-printing from result display, remove loop #59218

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Aug 12, 2025
84 changes: 47 additions & 37 deletions stdlib/REPL/src/REPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,11 @@ function print_response(repl::AbstractREPL, response, show_value::Bool, have_col
return nothing
end

function repl_display_error(errio::IO, @nospecialize errval)
# N.B.: Any functions starting with __repl_entry cut off backtraces when printing in the REPL.
__repl_entry_display(val) = Base.invokelatest(display, val)
__repl_entry_display(specialdisplay::Union{AbstractDisplay,Nothing}, val) = Base.invokelatest(display, specialdisplay, val)

function __repl_entry_display_error(errio::IO, @nospecialize errval)
# this will be set to true if types in the stacktrace are truncated
limitflag = Ref(false)
errio = IOContext(errio, :stacktrace_types_limited => limitflag)
Expand All @@ -593,53 +597,59 @@ end
function print_response(errio::IO, response, backend::Union{REPLBackendRef,Nothing}, show_value::Bool, have_color::Bool, specialdisplay::Union{AbstractDisplay,Nothing}=nothing)
Base.sigatomic_begin()
val, iserr = response
while true
if !iserr
# display result
try
Base.sigatomic_end()
if iserr
val = Base.scrub_repl_backtrace(val)
Base.istrivialerror(val) || setglobal!(Base.MainInclude, :err, val)
repl_display_error(errio, val)
else
if val !== nothing && show_value
val2, iserr = if specialdisplay === nothing
# display calls may require being run on the main thread
call_on_backend(backend) do
Base.invokelatest(display, val)
end
else
call_on_backend(backend) do
Base.invokelatest(display, specialdisplay, val)
end
if val !== nothing && show_value
Base.sigatomic_end() # allow display to be interrupted
val2, iserr = if specialdisplay === nothing
# display calls may require being run on the main thread
call_on_backend(backend) do
__repl_entry_display(val)
end
if iserr
println(errio, "Error showing value of type ", typeof(val), ":")
throw(val2)
else
call_on_backend(backend) do
__repl_entry_display(specialdisplay, val)
end
end
end
break
catch ex
if iserr
println(errio) # an error during printing is likely to leave us mid-line
println(errio, "SYSTEM (REPL): showing an error caused an error")
try
excs = Base.scrub_repl_backtrace(current_exceptions())
setglobal!(Base.MainInclude, :err, excs)
repl_display_error(errio, excs)
catch e
# at this point, only print the name of the type as a Symbol to
# minimize the possibility of further errors.
Base.sigatomic_begin()
if iserr
println(errio)
println(errio, "SYSTEM (REPL): caught exception of type ", typeof(e).name.name,
" while trying to handle a nested exception; giving up")
println(errio, "Error showing value of type ", typeof(val), ":")
val = val2
end
break
end
catch ex
println(errio)
println(errio, "SYSTEM (REPL): showing a value caused an error")
val = current_exceptions()
iserr = true
end
end
if iserr
# print error
iserr = false
while true
try
Base.sigatomic_end() # allow stacktrace printing to be interrupted
val = Base.scrub_repl_backtrace(val)
Base.istrivialerror(val) || setglobal!(Base.MainInclude, :err, val)
__repl_entry_display_error(errio, val)
break
catch ex
println(errio) # an error during printing is likely to leave us mid-line
if !iserr
println(errio, "SYSTEM (REPL): showing an error caused an error")
val = current_exceptions()
iserr = true
else
println(errio, "SYSTEM (REPL): caught exception of type ", typeof(ex).name.name,
" while trying to print an exception; giving up")
break
end
end
end
end
Base.sigatomic_end()
nothing
end
Expand Down