Does JET not detect the UndefRefError in this code?

julia> using StaticArrays, LinearAlgebra, JET

julia> M = Matrix{BigInt}(undef, 2, 2); M[1,1] = M[2,2] = M[1,2] = 3; M
2×2 Matrix{BigInt}:
   3     3
 #undef  3

julia> S = SizedMatrix{2,2}(M)
2×2 SizedMatrix{2, 2, BigInt, 2, Matrix{BigInt}} with indices SOneTo(2)×SOneTo(2):
   3     3
 #undef  3

julia> @report_call triu(S)
No errors detected


julia> triu(S)
ERROR: UndefRefError: access to undefined reference
Stacktrace:
 [1] getindex
   @ ./essentials.jl:905 [inlined]
 [2] getindex
   @ ~/.julia/packages/StaticArrays/MSJcA/src/SizedArray.jl:92 [inlined]
 [3] copyto_unaliased!
   @ ./abstractarray.jl:1081 [inlined]
 [4] copyto!(dest::SizedMatrix{2, 2, BigInt, 2, Matrix{BigInt}}, src::SizedMatrix{2, 2, BigInt, 2, Matrix{BigInt}})
   @ Base ./abstractarray.jl:1061
 [5] copymutable
   @ ./abstractarray.jl:1195 [inlined]
 [6] triu(M::SizedMatrix{2, 2, BigInt, 2, Matrix{BigInt}})
   @ LinearAlgebra ~/.julia/juliaup/julia-1.11.0-rc2+0.x64.linux.gnu/share/julia/stdlib/v1.11/LinearAlgebra/src/generic.jl:347
 [7] top-level scope
   @ REPL[14]:1

Does JET not recognize such errors?

1 Like

The sound analysis mode should catch the possible throw, I guess, but it actually produces a possibly overwhelming amount of output. Try @report_call mode=:sound triu(S).

1 Like

I don’t think Jet.jl can reasonably detect these kinds of error and I somewhat doubt that it is a useful question to ask in the first place. This error is essentially a problem with a specific value in the matrix. So whether a given indexing operation fails or not is specific to the array you are indexing. I think the only two options are to mark either none or all calls to getindex of an Array supporting #undef.
Or is there some mechanism that can track whether undefined references can exist at all? That might help a bit. I seem to remember that I read some github discussion about some compiler optimization in this direction once… I’ll try to find it.

But even then I don’t think checking for possible UndefRefErrors is fruitful. An example:

function chaseIndex(arr)
    at = first(arr)
    while checkbounds(Bool, arr, at)
        at = arr[at]
    end
    return at
end

Determining for a given matrix whether you reach a contained #undef is basically equivalent to running the function on that input and checking whether it throws. So I think, you will never be able to make a meaningful static check of UndefRefError. Either you report every getindex as potentially throwing or you don’t. The latter seems preferable to me.

Edit: I think what I read was not about undefined values in an array but rather for a struct. A struct tracks which of its fields could potentially be left undefined.

@abraemer I suggest checking out the JET.jl docs on the sound analysis mode, and also aviatesk’s blog if you’re interested in this:

The idea with the sound analysis mode is that an error is reported when JET couldn’t prove there’s no error (throw).

Yes, as I said already, this can produce an overwhelming amount of output, but in some cases it might be useful, perhaps for workflows targeting a GPU or microcontroller.

1 Like