Open aviatesk opened 3 years ago
Another target example would be:
isequal(t1::Tuple, t2::Tuple) = (length(t1) == length(t2)) && _isequal(t1, t2) _isequal(t1::Tuple{}, t2::Tuple{}) = true _isequal(t1::Tuple{Any}, t2::Tuple{Any}) = isequal(t1[1], t2[1]) _isequal(t1::Tuple, t2::Tuple) = isequal(t1[1], t2[1]) && _isequal(tail(t1), tail(t2)) function _isequal(t1::Any32, t2::Any32) for i = 1:length(t1) if !isequal(t1[i], t2[i]) return false end end return true end
isequal(::Any, ::Tuple{Any})
is always valid given the definition above, but JET reports false positive on this:
julia> report_call((Any, Tuple{Any}); annotate_types=true) do t1, t2
isequal(t1, t2)
end
═════ 1 possible error found ═════
┌ @ none:2 Main.isequal(t1::Any, t2::Tuple{Any})
│┌ @ /Users/aviatesk/julia/julia/base/tuple.jl:360 Base._isequal(t1::Tuple, t2::Tuple{Any})
││┌ @ /Users/aviatesk/julia/julia/base/tuple.jl:363 Base._isequal(Base.tail(t1::Tuple)::Tuple, Base.tail(t2::Tuple{Any})::Tuple{})
│││┌ @ /Users/aviatesk/julia/julia/base/tuple.jl:363 Base.getindex(t2::Tuple{}, 1)
││││┌ @ tuple.jl:29 Base.getfield(t::Tuple{}, i::Int64, $(Expr(:boundscheck)))
│││││ invalid builtin function call: Base.getfield(t::Tuple{}, i::Int64, $(Expr(:boundscheck)))
││││└───────────────
Any
https://github.com/JuliaLang/julia/pull/40594 is a band-aid for the time being.
something like described in this paper: https://www-apr.lip6.fr/~mine/publi/article-monat-al-ecoop20.pdf
I found there're certainly cases where a relational analysis can improve the analysis accuracy: