Which getindex expression threw BoundsError

I often make this kind of mistake. Would it be possible for the error to figure out which subexpression has the problem, to save me time debugging?

julia> let n = 2, m = 3
           xs = randn(n)
           ys = randn(m)
           xs[m] + ys[n]
       end
ERROR: BoundsError: attempt to access 2-element Vector{Float64} at index [3]
Stacktrace:
 [1] getindex(A::Vector{Float64}, i1::Int64)
   @ Base ./essentials.jl:13
 [2] top-level scope

image

Unfortunately, lowering doesn’t give enough information here. Only the source line is preserved, not the textual column or subexpression.

Having that kind of information would be very beneficial, not just for better identifying the source of errors. Some examples can be found here:

EDIT: I’ve added this discourse thread as an “this would be enabled by better coverage reporting” entry to the list of cool things.

2 Likes

I’ve run into this kind of problem across many languages. It’s uncommon for stack traces to include column information, so if there’s a complex expression, it can be challenging to figure out which part of it is throwing an error.

The workaround while debugging is to put each part of the expression on its own line, something like this:

let n = 2, m = 3
           xs = randn(n)
           ys = randn(m)
           (xs[m] + 
            ys[n])
       end
end

Obviously you wouldn’t want to leave a program in this state! But this will give xs[m] and ys[n] lines of their own, so the stacktrace of the BoundsError will tell you which one is out-of-bounds.

A justification for only showing line number is that you often shouldn’t only scrutinize the call that threw the error, whether it’s a meaningful subexpression, the whole line, an important series of lines, a whole scope, or possibly more. As you can tell from the example, xs[m] threw the error because length(xs) == n == 2 but m == 3, so you can get around the error with xs[n]. But xs[n] + ys[n] is unlikely to be the right fix because most of us would notice different indices as a typo sooner if the same indices were intended. The more likely typo is swapping indices, which is fixed by xs[n] + ys[m]. Whichever is the right fix, it’s important to look around the error. Still, you can do that anyways if a column number was reported indicating the erroring call, and that’s not much more to print.

Yes, but

This isn’t enough. Assigning xs[m] and ys[n] to variables is. The problem is that, after some compilation stage, Julia doesn’t know that the expression has more than one line. I guess that lowering is to blame here, according to Sukera?

I wonder how relevant this message still is (since then we got JuliaSyntax.jl and LLVM could have gotten some relevant improvements, too?):

Somewhat related issues on Github:

New issue:

1 Like