These stack traces are out of control

I just got a stack trace that has exceeded the scroll back on the VSCode terminal:

 [15] __solve(::ODEProblem{Array{Float64,1},Tuple{Float64,Float64},true,DiffEqBase.NullParameters,DiffEqBase.ODEFunction{true,DiffEqSensitivity.ODEInterpolatingAdjointSensitivityFunction{DiffEqSensitivity.AdjointDiffCache{Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Base.OneTo{Int64},UnitRange{Int64},LinearAlgebra.UniformScaling{Bool}},InterpolatingAdjoint{0,true,Val{:central},Bool,Bool},Array{Float64,1},OrdinaryDiffEq.ODECompositeSolution{Float64,2,Array{Array{Float64,1},1},Nothing,Nothing,Array{Float64,1},Array{Array{Array{Float64,1},1},1},ODEProblem{Array{Float64,1},Tuple{Float64,Float64},false,DiffEqBase.NullParameters,DiffEqBase.ODEFunction{false,var"#258#259",LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}},DiffEqBase.StandardODEProblem},OrdinaryDiffEq.CompositeAlgorithm{Tuple{OrdinaryDiffEq.Tsit5,OrdinaryDiffEq.Rosenbrock23{0,false,DiffEqBase.DefaultLinSolve,DataType}},OrdinaryDiffEq.AutoSwitchCache{OrdinaryDiffEq.Tsit5,OrdinaryDiffEq.Rosenbrock23{0,false,DiffEqBase.DefaultLinSolve,DataType},Rational{Int64},Int64}},OrdinaryDiffEq.CompositeInterpolationData{DiffEqBase.ODEFunction{false,var"#258#259",LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Array{Float64,1},1},Array{Float64,1},Array{Array{Array{Float64,1},1},1},OrdinaryDiffEq.CompositeCache{Tuple{OrdinaryDiffEq.Tsit5ConstantCache{Float64,Float64},OrdinaryDiffEq.Rosenbrock23ConstantCache{Float64,DiffEqBase.TimeDerivativeWrapper{DiffEqBase.ODEFunction{false,var"#258#259",LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Float64,1},DiffEqBase.NullParameters},DiffEqBase.UDerivativeWrapper{DiffEqBase.ODEFunction{false,var"#258#259",LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Array{Float64,2},LinearAlgebra.LU{Float64,Array{Float64,2}},DiffEqBase.DefaultLinSolve}},OrdinaryDiffEq.AutoSwitchCache{OrdinaryDiffEq.Tsit5,OrdinaryDiffEq.Rosenbrock23{0,false,DiffEqBase.DefaultLinSolve,DataType},Rational{Int64},Int64}}},DiffEqBase.DEStats},Nothing,ODEProblem{Array{Float64,1},Tuple{Float64,Float64},false,DiffEqBase.NullParameters,DiffEqBase.ODEFunction{false,var"#258#259",LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}},DiffEqBase.StandardODEProblem},DiffEqBase.ODEFunction{false,var"#258#259",LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing}},LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Base.Iterators.Pairs{Symbol,DiffEqBase.CallbackSet{Tuple{},Tuple{DiscreteCallback{DiffEqCallbacks.var"#33#38"{Base.RefValue{Union{Nothing, Float64}}},DiffEqCallbacks.var"#34#39"{DiffEqSensitivity.var"#94#96"{Base.RefValue{Int64},Array{Float64,1}},DiffEqSensitivity.var"#95#97"{var"#260#261",InterpolatingAdjoint{0,true,Val{:central},Bool,Bool},Base.OneTo{Int64},UnitRange{Int64},LinearAlgebra.UniformScaling{Bool},Bool,Nothing,Nothing,Nothing,Nothing,Bool,Array{Float64,1},Array{Float64,1},Array{Float64,1},Base.RefValue{Int64},Int64,LinearAlgebra.UniformScaling{Bool}},Base.RefValue{Union{Nothing, Float64}}},DiffEqCallbacks.var"#35#40"{Bool,DiffEqCallbacks.var"#37#42"{Bool},DiffEqSensitivity.var"#94#96"{Base.RefValue{Int64},Array{Float64,1}},Base.RefValue{Union{Nothing, Float64}},DiffEqCallbacks.var"#34#39"{DiffEqSensitivity.var"#94#96"{Base.RefValue{Int64},Array{Float64,1}},DiffEqSensitivity.var"#95#97"{var"#260#261",InterpolatingAdjoint{0,true,Val{:central},Bool,Bool},Base.OneTo{Int64},UnitRange{Int64},LinearAlgebra.UniformScaling{Bool},Bool,Nothing,Nothing,Nothing,Nothing,Bool,Array{Float64,1},Array{Float64,1},Array{Float64,1},Base.RefValue{Int64},Int64,LinearAlgebra.UniformScaling{Bool}},Base.RefValue{Union{Nothing, Float64}}}}}}},Tuple{Symbol},NamedTuple{(:callback,),Tuple{DiffEqBase.CallbackSet{Tuple{},Tuple{DiscreteCallback{DiffEqCallbacks.var"#33#38"{Base.RefValue{Union{Nothing, Float64}}},DiffEqCallbacks.var"#34#39"{DiffEqSensitivity.var"#94#96"{Base.RefValue{Int64},Array{Float64,1}},DiffEqSensitivity.var"#95#97"{var"#260#261",InterpolatingAdjoint{0,true,Val{:central},Bool,Bool},Base.OneTo{Int64},UnitRange{Int64},LinearAlgebra.UniformScaling{Bool},Bool,Nothing,Nothing,Nothing,Nothing,Bool,Array{Float64,1},Array{Float64,1},Array{Float64,1},Base.RefValue{Int64},Int64,LinearAlgebra.UniformScaling{Bool}},Base.RefValue{Union{Nothing, Float64}}},DiffEqCallbacks.var"#35#40"{Bool,DiffEqCallbacks.var"#37#42"{Bool},DiffEqSensitivity.var"#94#96"{Base.RefValue{Int64},Array{Float64,1}},Base.RefValue{Union{Nothing, Float64}},DiffEqCallbacks.var"#34#39"{DiffEqSensitivity.var"#94#96"{Base.RefValue{Int64},Array{Float64,1}},DiffEqSensitivity.var"#95#97"{var"#260#261",InterpolatingAdjoint{0,true,Val{:central},Bool,Bool},Base.OneTo{Int64},UnitRange{Int64},LinearAlgebra.UniformScaling{Bool},Bool,Nothing,Nothing,Nothing,Nothing,Bool,Array{Float64,1},Array{Float64,1},Array{Float64,1},Base.RefValue{Int64},Int64,LinearAlgebra.UniformScaling{Bool}},Base.RefValue{Union{Nothing, Float64}}}}}}}}}},DiffEqBase.StandardODEProblem}, ::Nothing; default_set::Bool, kwargs::Base.Iterators.Pairs{Symbol,Any,Tuple{Symbol,Symbol},NamedTuple{(:second_time, :callback),Tuple{Bool,DiffEqBase.CallbackSet{Tuple{},Tuple{DiscreteCallback{DiffEqCallbacks.var"#33#38"{Base.RefValue{Union{Nothing, Float64}}},DiffEqCallbacks.var"#34#39"{DiffEqSensitivity.var"#94#96"{Base.RefValue{Int64},Array{Float64,1}},DiffEqSensitivity.var"#95#97"{var"#260#261",InterpolatingAdjoint{0,true,Val{:central},Bool,Bool},Base.OneTo{Int64},UnitRange{Int64},LinearAlgebra.UniformScaling{Bool},Bool,Nothing,Nothing,Nothing,Nothing,Bool,Array{Float64,1},Array{Float64,1},Array{Float64,1},Base.RefValue{Int64},Int64,LinearAlgebra.UniformScaling{Bool}},Base.RefValue{Union{Nothing, Float64}}},DiffEqCallbacks.var"#35#40"{Bool,DiffEqCallbacks.var"#37#42"{Bool},DiffEqSensitivity.var"#94#96"{Base.RefValue{Int64},Array{Float64,1}},Base.RefValue{Union{Nothing, Float64}},DiffEqCallbacks.var"#34#39"{DiffEqSensitivity.var"#94#96"{Base.RefValue{Int64},Array{Float64,1}},DiffEqSensitivity.var"#95#97"{var"#260#261",InterpolatingAdjoint{0,true,Val{:central},Bool,Bool},Base.OneTo{Int64},UnitRange{Int64},LinearAlgebra.UniformScaling{Bool},Bool,Nothing,Nothing,Nothing,Nothing,Bool,Array{Float64,1},Array{Float64,1},Array{Float64,1},Base.RefValue{Int64},Int64,LinearAlgebra.UniformScaling{Bool}},Base.RefValue{Union{Nothing, Float64}}}}}}}}}}) at /home/samuela/.julia/packages/DifferentialEquations/fpohE/src/default_solve.jl:7
 [16] #__solve#468 at /home/samuela/.julia/packages/DiffEqBase/kRzKx/src/solve.jl:230 [inlined]
 [17] solve_call(::ODEProblem{Array{Float64,1},Tuple{Float64,Float64},true,DiffEqBase.NullParameters,DiffEqBase.ODEFunction{true,DiffEqSensitivity.ODEInterpolatingAdjointSensitivityFunction{DiffEqSensitivity.AdjointDiffCache{Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Base.OneTo{Int64},UnitRange{Int64},LinearAlgebra.UniformScaling{Bool}},InterpolatingAdjoint{0,true,Val{:central},Bool,Bool},Array{Float64,1},OrdinaryDiffEq.ODECompositeSolution{Float64,2,Array{Array{Float64,1},1},Nothing,Nothing,Array{Float64,1},Array{Array{Array{Float64,1},1},1},ODEProblem{Array{Float64,1},Tuple{Float64,Float64},false,DiffEqBase.NullParameters,DiffEqBase.ODEFunction{false,var"#258#259",LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}},DiffEqBase.StandardODEProblem},OrdinaryDiffEq.CompositeAlgorithm{Tuple{OrdinaryDiffEq.Tsit5,OrdinaryDiffEq.Rosenbrock23{0,false,DiffEqBase.DefaultLinSolve,DataType}},OrdinaryDiffEq.AutoSwitchCache{OrdinaryDiffEq.Tsit5,OrdinaryDiffEq.Rosenbrock23{0,false,DiffEqBase.DefaultLinSolve,DataType},Rational{Int64},Int64}},OrdinaryDiffEq.CompositeInterpolationData{DiffEqBase.ODEFunction{false,var"#258#259",LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Array{Float64,1},1},Array{Float64,1},Array{Array{Array{Float64,1},1},1},OrdinaryDiffEq.CompositeCache{Tuple{OrdinaryDiffEq.Tsit5ConstantCache{Float64,Float64},OrdinaryDiffEq.Rosenbrock23ConstantCache{Float64,DiffEqBase.TimeDerivativeWrapper{DiffEqBase.ODEFunction{false,var"#258#259",LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Float64,1},DiffEqBase.NullParameters},DiffEqBase.UDerivativeWrapper{DiffEqBase.ODEFunction{false,var"#258#259",LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Array{Float64,2},LinearAlgebra.LU{Float64,Array{Float64,2}},DiffEqBase.DefaultLinSolve}},OrdinaryDiffEq.AutoSwitchCache{OrdinaryDiffEq.Tsit5,OrdinaryDiffEq.Rosenbrock23{0,false,DiffEqBase.DefaultLinSolve,DataType},Rational{Int64},Int64}}},DiffEqBase.DEStats},Nothing,ODEProblem{Array{Float64,1},Tuple{Float64,Float64},false,DiffEqBase.NullParameters,DiffEqBase.ODEFunction{false,var"#258#259",LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}},DiffEqBase.StandardODEProblem},DiffEqBase.ODEFunction{false,var"#258#259",LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing}},LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Base.Iterators.Pairs{Symbol,DiffEqBase.CallbackSet{Tuple{},Tuple{DiscreteCallback{DiffEqCallbacks.var"#33#38"{Base.RefValue{Union{Nothing, Float64}}},DiffEqCallbacks.var"#34#39"{DiffEqSensitivity.var"#94#96"{Base.RefValue{Int64},Array{Float64,1}},DiffEqSensitivity.var"#95#97"{var"#260#261",InterpolatingAdjoint{0,true,Val{:central},Bool,Bool},Base.OneTo{Int64},UnitRange{Int64},LinearAlgebra.UniformScaling{Bool},Bool,Nothing,Nothing,Nothing,Nothing,Bool,Array{Float64,1},Array{Float64,1},Array{Float64,1},Base.RefValue{Int64},Int64,LinearAlgebra.UniformScaling{Bool}},Base.RefValue{Union{Nothing, Float64}}},DiffEqCallbacks.var"#35#40"{Bool,DiffEqCallbacks.var"#37#42"{Bool},DiffEqSensitivity.var"#94#96"{Base.RefValue{Int64},Array{Float64,1}},Base.RefValue{Union{Nothing, Float64}},DiffEqCallbacks.var"#34#39"{DiffEqSensitivity.var"#94#96"{Base.RefValue{Int64},Array{Float64,1}},DiffEqSensitivity.var"#95#97"{var"#260#261",InterpolatingAdjoint{0,true,Val{:central},Bool,Bool},Base.OneTo{Int64},UnitRange{Int64},LinearAlgebra.UniformScaling{Bool},Bool,Nothing,Nothing,Nothing,Nothing,Bool,Array{Float64,1},Array{Float64,1},Array{Float64,1},Base.RefValue{Int64},Int64,LinearAlgebra.UniformScaling{Bool}},Base.RefValue{Union{Nothing, Float64}}}}}}},Tuple{Symbol},NamedTuple{(:callback,),Tuple{DiffEqBase.CallbackSet{Tuple{},Tuple{DiscreteCallback{DiffEqCallbacks.var"#33#38"{Base.RefValue{Union{Nothing, Float64}}},DiffEqCallbacks.var"#34#39"{DiffEqSensitivity.var"#94#96"{Base.RefValue{Int64},Array{Float64,1}},DiffEqSensitivity.var"#95#97"{var"#260#261",InterpolatingAdjoint{0,true,Val{:central},Bool,Bool},Base.OneTo{Int64},UnitRange{Int64},LinearAlgebra.UniformScaling{Bool},Bool,Nothing,Nothing,Nothing,Nothing,Bool,Array{Float64,1},Array{Float64,1},Array{Float64,1},Base.RefValue{Int64},Int64,LinearAlgebra.UniformScaling{Bool}},Base.RefValue{Union{Nothing, Float64}}},DiffEqCallbacks.var"#35#40"{Bool,DiffEqCallbacks.var"#37#42"{Bool},DiffEqSensitivity.var"#94#96"{Base.RefValue{Int64},Array{Float64,1}},Base.RefValue{Union{Nothing, Float64}},DiffEqCallbacks.var"#34#39"{DiffEqSensitivity.var"#94#96"{Base.RefValue{Int64},Array{Float64,1}},DiffEqSensitivity.var"#95#97"{var"#260#261",InterpolatingAdjoint{0,true,Val{:central},Bool,Bool},Base.OneTo{Int64},UnitRange{Int64},LinearAlgebra.UniformScaling{Bool},Bool,Nothing,Nothing,Nothing,Nothing,Bool,Array{Float64,1},Array{Float64,1},Array{Float64,1},Base.RefValue{Int64},Int64,LinearAlgebra.UniformScaling{Bool}},Base.RefValue{Union{Nothing, Float64}}}}}}}}}},DiffEqBase.StandardODEProblem}; merge_callbacks::Bool, kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at /home/samuela/.julia/packages/DiffEqBase/kRzKx/src/solve.jl:65
 [18] solve_call at /home/samuela/.julia/packages/DiffEqBase/kRzKx/src/solve.jl:52 [inlined]
 [19] #solve_up#458 at /home/samuela/.julia/packages/DiffEqBase/kRzKx/src/solve.jl:89 [inlined]
 [20] solve_up at /home/samuela/.julia/packages/DiffEqBase/kRzKx/src/solve.jl:79 [inlined]
 [21] #solve#457 at /home/samuela/.julia/packages/DiffEqBase/kRzKx/src/solve.jl:74 [inlined]
 [22] solve(::ODEProblem{Array{Float64,1},Tuple{Float64,Float64},true,DiffEqBase.NullParameters,DiffEqBase.ODEFunction{true,DiffEqSensitivity.ODEInterpolatingAdjointSensitivityFunction{DiffEqSensitivity.AdjointDiffCache{Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Base.OneTo{Int64},UnitRange{Int64},LinearAlgebra.UniformScaling{Bool}},InterpolatingAdjoint{0,true,Val{:central},Bool,Bool},Array{Float64,1},OrdinaryDiffEq.ODECompositeSolution{Float64,2,Array{Array{Float64,1},1},Nothing,Nothing,Array{Float64,1},Array{Array{Array{Float64,1},1},1},ODEProblem{Array{Float64,1},Tuple{Float64,Float64},false,DiffEqBase.NullParameters,DiffEqBase.ODEFunction{false,var"#258#259",LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}},DiffEqBase.StandardODEProblem},OrdinaryDiffEq.CompositeAlgorithm{Tuple{OrdinaryDiffEq.Tsit5,OrdinaryDiffEq.Rosenbrock23{0,false,DiffEqBase.DefaultLinSolve,DataType}},OrdinaryDiffEq.AutoSwitchCache{OrdinaryDiffEq.Tsit5,OrdinaryDiffEq.Rosenbrock23{0,false,DiffEqBase.DefaultLinSolve,DataType},Rational{Int64},Int64}},OrdinaryDiffEq.CompositeInterpolationData{DiffEqBase.ODEFunction{false,var"#258#259",LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Array{Float64,1},1},Array{Float64,1},Array{Array{Array{Float64,1},1},1},OrdinaryDiffEq.CompositeCache{Tuple{OrdinaryDiffEq.Tsit5ConstantCache{Float64,Float64},OrdinaryDiffEq.Rosenbrock23ConstantCache{Float64,DiffEqBase.TimeDerivativeWrapper{DiffEqBase.ODEFunction{false,var"#258#259",LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Float64,1},DiffEqBase.NullParameters},DiffEqBase.UDerivativeWrapper{DiffEqBase.ODEFunction{false,var"#258#259",LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Array{Float64,2},LinearAlgebra.LU{Float64,Array{Float64,2}},DiffEqBase.DefaultLinSolve}},OrdinaryDiffEq.AutoSwitchCache{OrdinaryDiffEq.Tsit5,OrdinaryDiffEq.Rosenbrock23{0,false,DiffEqBase.DefaultLinSolve,DataType},Rational{Int64},Int64}}},DiffEqBase.DEStats},Nothing,ODEProblem{Array{Float64,1},Tuple{Float64,Float64},false,DiffEqBase.NullParameters,DiffEqBase.ODEFunction{false,var"#258#259",LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}},DiffEqBase.StandardODEProblem},DiffEqBase.ODEFunction{false,var"#258#259",LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing}},LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Base.Iterators.Pairs{Symbol,DiffEqBase.CallbackSet{Tuple{},Tuple{DiscreteCallback{DiffEqCallbacks.var"#33#38"{Base.RefValue{Union{Nothing, Float64}}},DiffEqCallbacks.var"#34#39"{DiffEqSensitivity.var"#94#96"{Base.RefValue{Int64},Array{Float64,1}},DiffEqSensitivity.var"#95#97"{var"#260#261",InterpolatingAdjoint{0,true,Val{:central},Bool,Bool},Base.OneTo{Int64},UnitRange{Int64},LinearAlgebra.UniformScaling{Bool},Bool,Nothing,Nothing,Nothing,Nothing,Bool,Array{Float64,1},Array{Float64,1},Array{Float64,1},Base.RefValue{Int64},Int64,LinearAlgebra.UniformScaling{Bool}},Base.RefValue{Union{Nothing, Float64}}},DiffEqCallbacks.var"#35#40"{Bool,DiffEqCallbacks.var"#37#42"{Bool},DiffEqSensitivity.var"#94#96"{Base.RefValue{Int64},Array{Float64,1}},Base.RefValue{Union{Nothing, Float64}},DiffEqCallbacks.var"#34#39"{DiffEqSensitivity.var"#94#96"{Base.RefValue{Int64},Array{Float64,1}},DiffEqSensitivity.var"#95#97"{var"#260#261",InterpolatingAdjoint{0,true,Val{:central},Bool,Bool},Base.OneTo{Int64},UnitRange{Int64},LinearAlgebra.UniformScaling{Bool},Bool,Nothing,Nothing,Nothing,Nothing,Bool,Array{Float64,1},Array{Float64,1},Array{Float64,1},Base.RefValue{Int64},Int64,LinearAlgebra.UniformScaling{Bool}},Base.RefValue{Union{Nothing, Float64}}}}}}},Tuple{Symbol},NamedTuple{(:callback,),Tuple{DiffEqBase.CallbackSet{Tuple{},Tuple{DiscreteCallback{DiffEqCallbacks.var"#33#38"{Base.RefValue{Union{Nothing, Float64}}},DiffEqCallbacks.var"#34#39"{DiffEqSensitivity.var"#94#96"{Base.RefValue{Int64},Array{Float64,1}},DiffEqSensitivity.var"#95#97"{var"#260#261",InterpolatingAdjoint{0,true,Val{:central},Bool,Bool},Base.OneTo{Int64},UnitRange{Int64},LinearAlgebra.UniformScaling{Bool},Bool,Nothing,Nothing,Nothing,Nothing,Bool,Array{Float64,1},Array{Float64,1},Array{Float64,1},Base.RefValue{Int64},Int64,LinearAlgebra.UniformScaling{Bool}},Base.RefValue{Union{Nothing, Float64}}},DiffEqCallbacks.var"#35#40"{Bool,DiffEqCallbacks.var"#37#42"{Bool},DiffEqSensitivity.var"#94#96"{Base.RefValue{Int64},Array{Float64,1}},Base.RefValue{Union{Nothing, Float64}},DiffEqCallbacks.var"#34#39"{DiffEqSensitivity.var"#94#96"{Base.RefValue{Int64},Array{Float64,1}},DiffEqSensitivity.var"#95#97"{var"#260#261",InterpolatingAdjoint{0,true,Val{:central},Bool,Bool},Base.OneTo{Int64},UnitRange{Int64},LinearAlgebra.UniformScaling{Bool},Bool,Nothing,Nothing,Nothing,Nothing,Bool,Array{Float64,1},Array{Float64,1},Array{Float64,1},Base.RefValue{Int64},Int64,LinearAlgebra.UniformScaling{Bool}},Base.RefValue{Union{Nothing, Float64}}}}}}}}}},DiffEqBase.StandardODEProblem}) at /home/samuela/.julia/packages/DiffEqBase/kRzKx/src/solve.jl:72
 [23] top-level scope at /home/samuela/dev/research/julia/odecontrol/difftaichi/callback_hell.jl:82
 [24] include(::String) at ./client.jl:457
 [25] top-level scope at REPL[21]:1
in expression starting at /home/samuela/dev/research/julia/odecontrol/difftaichi/callback_hell.jl:80

Turning off word wrap is not for the faint of heart…

4 Likes

I couldn’t even post the whole (still cut off) version due to Discourse’s post limits:

9 Likes

A little trick for this that I realized others may not be aware of: use ; tput rmam at the REPL to enable line-cropping, and ; tput smam to disable it.

9 Likes

This is a good point, and I imagine a common annoyance. It’s invariably caused by types that have many (often nested) type parameters for performance reasons. I wonder if it should become good practice to overload show on the type itself in these cases to avoid long errors.
E.g.

struct Complicated{a,b,c,d,e,f,g} end
Base.show(io::IO, T::Type{<:Complicated}) = print(io, "Complicated")

You need to overload another method to get a short printout when you want it, but still be able to print the full typeof(C) (e.g. at the repl), which is useful. I tried my hand at a quick macro for this, shown below

macro complicated(ex)
    ex.head == :struct || error("invalid use of @complicated")
    typeex = ex.args[2]   # This is the "type" line
    typeex isa Symbol && return ex  # has no parameters

    type = typeex.args[1]

    quote
        $ex
        
        function Base.show(io::IO, ::MIME"text/plain", T::Type{<:$type})
            if T isa UnionAll
                print(io, T)
            else
                print(io, "$(Base.typename(T)){$(join(T.parameters, ", "))}")
            end
        end

        Base.show(io::IO, T::Type{<:$type}) = print(io, Base.typename(T))
    end
end
julia> @complicated struct Complicated{a,b,c,d,e,f,g} end

julia> C = Complicated{ntuple(i->Float64, 7)...}()
Complicated()

julia> typeof(C)
Complicated{Float64, Float64, Float64, Float64, Float64, Float64, Float64}

julia> f(x) = g(x); g(x) = h(x); h(x) = x + 1 #### create a contrived stacktrace
h (generic function with 1 method)

julia> f(C)
ERROR: MethodError: no method matching +(::Complicated, ::Int64)
  # ...
Stacktrace:
 [1] h(::Complicated) at ./REPL[35]:1
 [2] g(::Complicated) at ./REPL[35]:1
 [3] f(::Complicated) at ./REPL[35]:1
 [4] top-level scope at REPL[36]:1

::Complicated is printed compactly everywhere in the stacktrace above, since it isn’t a MIME"text/plain" context.
Unfortunately, this can hide certain bugs when a type parameter is what’s causing the MethodError, which is a big drawback. See:

julia> fg(C::Complicated{Int}) = C
fg (generic function with 1 method)

julia> fg(C)
ERROR: MethodError: no method matching fg(::Complicated)
Closest candidates are:
  fg(::Complicated) at REPL[51]:1

I don’t know how to solve both problems though :man_shrugging:


Edit: I guess the way to solve both problems is a flag in the IOContext to determine whether it’s important to display parameter information (e.g. if it’s a “closest candidates” method recommendation, or the top level error message). Stacktraces could then by default have parameters muted.

3 Likes

Unfortunately,

The first reason is that, according to the compiler team, the base methods are not supposed to be overloaded. It’s not documented and not obvious but it’s been assumed that show(::IO, ::Type) isn’t overloaded by user code so doing that can lead to very odd issues. E.g. the definitions in this package might have caused Documenter to hang for one of my packages because Documenter prints the signature of methods with missing docs.

2 Likes

As per my edit, the solution is to check a flag in the relevant show method. A lot of digging later (and also my first time using Debugger.jl, which was awesome, by the way), I found out this can be done by modifying this line in Base.

It’s quite a long function so I’m hiding it, but the diff between this and Base is 3 lines (and could technically be just one).

Summary
@eval Base function show_tuple_as_call(io::IO, name::Symbol, sig::Type, demangle=false, kwargs=nothing)
    # print a method signature tuple for a lambda definition
    in_backtrace = get(io, :backtrace, false)
    color = get(io, :color, false) && in_backtrace ? stackframe_function_color() : :nothing
    if sig === Tuple
        printstyled(io, demangle ? demangle_function_name(name) : name, "(...)", color=color)
        return
    end
    tv = Any[]
    env_io = io
    while isa(sig, UnionAll)
        push!(tv, sig.var)
        env_io = IOContext(env_io, :unionall_env => sig.var)
        sig = sig.body
    end
    sig = sig.parameters
    with_output_color(color, env_io) do io
        ft = sig[1]
        uw = unwrap_unionall(ft)
        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))
        elseif isa(ft, DataType) && ft.name === Type.body.name && !Core.Compiler.has_free_typevars(ft)
            f = ft.parameters[1]
            print(io, f)
        else
            print(io, "(::", ft, ")")
        end
    end
    first = true
    
    print_style = get(io, :color, false) && in_backtrace ? :bold : :nothing
    printstyled(io, "(", color=print_style)
    for i = 2:length(sig)  # fixme (iter): `eachindex` with offset?
        first || print(io, ", ")
        first = false
        print(env_io, "::", in_backtrace ? typename(sig[i]) : sig[i])
    end
    if kwargs !== nothing
        print(io, "; ")
        first = true
        for (k, t) in kwargs
            first || print(io, ", ")
            first = false
            print(io, k, "::")
            show(io, t)
        end
    end
    printstyled(io, ")", color=print_style)
    show_method_params(io, tv)
    nothing
end

For the effect, see:

## Create a contrived stacktrace to see the effect
## and a similar method for h so we get "Closest candidates"
julia> begin 
           f(x) = g(x, x, x)
           g(x, y, z) = h(x, y, z)
           h(x::Complicated{Float64}, y::Complicated{Float64}) = "anything"
       end

julia> struct Complicated{a,b,c,d} end

julia> C = Complicated{ntuple(i->Float64, 4)...}()
Complicated{Float64,Float64,Float64,Float64}()

julia> f(C)
ERROR: MethodError: no method matching h(::Complicated{Float64,Float64,Float64,Float64}, ::Complicated{Float64,Float64,Float64,Float64}, ::Complicated{Float64,Float64,Float64,Float64})
Closest candidates are:
  h(::Complicated{Float64,b,c,d} where d where c where b, ::Complicated{Float64,b,c,d} where d where c where b) at REPL[16]:1
Stacktrace:
 [1] g(::Complicated, ::Complicated, ::Complicated) at ./REPL[16]:1
 [2] f(::Complicated) at ./REPL[16]:1
 [3] top-level scope at REPL[19]:1

We get the full method signature in the method error itself and in the closest candidates (which we may need to know to disambiguate the error), but the type name in the stacktrace is always shortened. It’s still worth considering I think whether this is behavior that should be enabled by default, or whether only certain “complicated” types should feature this, i.e. if this is opt-in by the struct creator.

1 Like

Note that this show function will be changed in 1.6 by #36134, which adds the argument names (and other things), and I hope by #37773, which de-emphasises type parameters (compared to the outermost type).

But perhaps it should shorten them too? Maybe even as crudely as cutting off at N characters? Or call some opt-in function, only used in stack-trace printing.

2 Likes

I personally like the idea that we could seperate type parameters that can be dispatched on, and thus must be shown,
from the idea of allowing fields to be specialized on for performance.

Somewhere there is a issue or thread discussing this.

3 Likes

Oooh, that would be quite interesting!

I remember this: https://github.com/JuliaLang/julia/issues/18466#issuecomment-274442844 .

1 Like

I didn’t know this was in the works! I am also in favor of shortening stacktraces; opt-in or out doesn’t matter to me personally, as long as one of the two options is available. I agree that cutting off at N characters might indeed be too crude, and I do like the idea of an opt-in function that would determine whether a type is printed compactly in a stacktrace context (and possibly other contexts). E.g.

shorten_in_stacktrace(::Type{<:MyType}) = true

I don’t know much about the internals of show, but I assume there is no type specialization anywhere in the stack so using a trait is out of the question, and therefore the above might be the easiest way for package authors to opt in?

Alternatively, a method that determines how the type will actually be printed could be interesting. E.g.

function show_in_stacktrace(io, MT::Type{<:MyType})
    print(io, "MyType{")
    for T in MT.parameters
        # example for how one might truncate the parameterizing 
        # types of a type. Realistically this needs to be an 
        # if-else for types vs. actual objects
        print(io, typename(T), ", ")
    end
    print(io, "}")
end

Although maybe the above has issues I am not foreseeing?

The internals of show seem pretty complicated! One possibility might be to load something like this onto the IOContexts already used for array printing:

julia> show(IOContext(stdout, :compact=>false, :limit=>true), MIME"text/plain"(), rand(1,20))
10×20 Array{Float64, 2}:  #  has … but all the digits.
 0.3938623569760644   0.853812531985632    …  0.6808491221341564   0.5840210557352783

If the way to opt out of truncated printing was to define a show method which checks this flag, i’m not sure whether that would still cause the Documenter etc. issues mentioned above.

No kidding! I learned a lot in the last day and a half…

I reused the :backtrace flag because it was already available in that method, but it would need to be replaced with a different flag in order to show for some types and not others. However, since this can be a type specific trait, it’s not clear where the (let’s call it :compact) flag would be set, since the relevant line in show_tuple_as_call is a loop over the types in the signature:

# taken from `show_tuple_as_call`
    first = true
    for i = 2:length(sig)
        first || print(io, ", ")
        first = false
        print(env_io, "::", in_backtrace ? typename(sig[i]) : sig[i])
    end

Since we want different types to have different behaviors (unlike what I did before, which was to only add the in_backtrace condition), each iteration of the loop may potentially need to reset :compact. A function as the flag would perhaps be just as good then.

If we relax the restriction that different types should print differently, then this can already be done with the :backtrace flag, or a new flag can be added and paired with an ENV variable to globally toggle this behavior. E.g. you could do

ENV["SHORTSTACK"] = true

to get type information globally omitted from stacktraces by toggling the :compact flag in the IOContext created in show_backtrace.

Improving stacktrace readability is always a laudable goal. However, in this case I think it’s worth asking some questions from a package design perspective. Does it really make sense to have a type like the following?

DiffEqSensitivity.AdjointDiffCache{
	Nothing,
	Nothing,
	Nothing,
	Nothing,
	Nothing,
	Nothing,
	Nothing,
	Nothing,
	Nothing,
	Nothing,
	Nothing,
	Nothing,
	Nothing,
	Base.OneTo{Int64},
	UnitRange{Int64},
	LinearAlgebra.UniformScaling{Bool}
}

It looks to me like there are too many optional, free parameters in this type. Here is the type definition copied and pasted from github:

struct AdjointDiffCache{UF,PF,G,TJ,PJT,uType,JC,GC,PJC,JNC,PJNC,rateType,DG,DI,AI,FM}
  uf::UF
  pf::PF
  g::G
  J::TJ
  pJ::PJT
  dg_val::uType
  jac_config::JC
  g_grad_config::GC
  paramjac_config::PJC
  jac_noise_config::JNC
  paramjac_noise_config::PJNC
  f_cache::rateType
  dg::DG
  diffvar_idxs::DI
  algevar_idxs::AI
  factorized_mass_matrix::FM
  issemiexplicitdae::Bool
end

Personally, I never like to have more than one or two optional fields in a struct. If I have more than that, then I probably need to refactor.

I don’t know anything about DifferentialEquations.jl, so take this with a grain of salt, but my gut feeling is that somewhere in the design space for the DiffEq ecosystem there is a better design that doesn’t go wild with optional parameters.

I’m not familiar with DifferentialEquations.jl, but in the cases where I’ve run into similar issues as the OP, most of the type parameters are usually redundant, in that they could be derived from the others, but are included to keep field types concrete. For these cases, the real solution would be having field types that can depend non-trivially on the type parameters, so something like

struct Dumdum{A, B}
    field1::f(A, B)
    field2::g(A, B)
end

There’s an old-but-open github issued on this, as well as the ComputedFieldTypes.jl package. I’m not sure how fully ComputedFieldTypes.jl meets these needs since I haven’t seriously used it, nor whether something like this might eventually make it into the language itself.

Not only would this clean up stack traces and other things that print out types, but would often also make code more readable.

For what it’s worth, to achieve something like the above, I’ve been doing things like

struct Dumdum{A, B}
    field1::Any
    field2::Any
end

function Base.getproperty(x::Dumdum{A, B}, sym::Symbol) where {A, B}
    if sym === :field1
        T = f(A, B)
    elseif sym === :field2
        T = g(A, B)
    else
        T = Any
    end
    return getfield(x, sym)::T
end

As long as the types of field1 and field2 weren’t going to be bits types, I don’t think there should be any loss of performance here. This does of course rely on type inference being able to figure out the type of x.field1, but at least in my use cases it does.

1 Like