Skip to content

JET warning for hash(::Rational) caused by inability to establish return type of Float64(x) #791

@fingolfin

Description

@fingolfin

In a package I am JETing (to be precise: AbstractAlgebra.jl, but it shouldn't matter) some code is uses Rational keys in a Dict, leading to this report, which baffles me. I'll write more below it:

││││││││┌ hashindex(key::Rational, sz::Int64) @ Base ./dict.jl:128
│││││││││┌ hash(x::Rational) @ Base ./hashing.jl:28
││││││││││┌ hash(x::Rational{<:Union{Int16, Int32, Int64, Int8, UInt16, UInt32, UInt64, UInt8}}, h::UInt64) @ Base ./rational.jl:600
│││││││││││┌ ldexp(x::T, e::Int64) where T<:Union{Float16, Float32, Float64} @ Base.Math ./math.jl:893
││││││││││││┌ reinterpret(::Type{T} where T<:Union{Float16, Float32, Float64}, x::UInt16) @ Base ./essentials.jl:736
│││││││││││││┌ _reinterpret(::Type{T} where T<:Union{Float16, Float32, Float64}, x::UInt16) @ Base ./reinterpretarray.jl:858
││││││││││││││┌ packedsize(::Type{T} where T<:Union{Float16, Float32, Float64}) @ Base ./reinterpretarray.jl:815
│││││││││││││││┌ padding(T::Type{T} where T<:Union{Float16, Float32, Float64}) @ Base ./reinterpretarray.jl:755
││││││││││││││││┌ padding(T::Type{T} where T<:Union{Float16, Float32, Float64}, baseoffset::Int64) @ Base ./reinterpretarray.jl:759
│││││││││││││││││ invalid builtin function call: fT = fieldtype(T::Type{T} where T<:Union{Float16, Float32, Float64}, i)
││││││││││││││││└────────────────────
│││││││││││││┌ _reinterpret(::Type{T} where T<:Union{Float16, Float32, Float64}, x::UInt16) @ Base ./reinterpretarray.jl:874
││││││││││││││┌ _reinterpret_padding(::Type{T} where T<:Union{Float16, Float32, Float64}, x::UInt16) @ Base ./reinterpretarray.jl:891
│││││││││││││││┌ _copyfrompacked!(ptr_out::Ptr{T} where T<:Union{Float16, Float32, Float64}, ptr_in::Ptr{UInt16}) @ Base ./reinterpretarray.jl:841
││││││││││││││││ invalid builtin function call: fT = fieldtype(Out::Type{T} where T<:Union{Float16, Float32, Float64}, i)
│││││││││││││││└────────────────────

So it calls the hash(x::Rational{<:BitInteger64}, h::UInt) method, and the trouble maybe starts in this line of it:

                return hash(ldexp(Float64(num),pow),h)

Note how the first argument to ldexp is Float64(num) which I'd expect is always a Float64. But for some reason, JET seems to think it could be any T<:Union{Float16, Float32, Float64} ?

Now, of course one can write Float64(x) methods that return something that's not a Float64, but I don't think any such method is in the system when I run JET. To verify this, I run the following code as an experiment (I am sure there's a better way to do that, but hey, it did the job for me ;-) ):

julia> x = Base.RefValue{Base.BitInteger64}();

julia> foo(x::Base.RefValue{Base.BitInteger64}) = Float64(x[]);

julia> @code_warntype foo(x)
MethodInstance for foo(::Base.RefValue{Union{Int16, Int32, Int64, Int8, UInt16, UInt32, UInt64, UInt8}})
  from foo(x::Base.RefValue{Union{Int16, Int32, Int64, Int8, UInt16, UInt32, UInt64, UInt8}}) @ Main REPL[4]:1
Arguments
  #self#::Core.Const(Main.foo)
  x::Base.RefValue{Union{Int16, Int32, Int64, Int8, UInt16, UInt32, UInt64, UInt8}}
Body::Float64
1 ─ %1 = Main.Float64::Core.Const(Float64)
│   %2 = Base.getindex(x)::Union{Int16, Int32, Int64, Int8, UInt16, UInt32, UInt64, UInt8}
│   %3 = (%1)(%2)::Float64
└──      return %3

So the compiler is able to establish the return type, but JET isn't?

Perhaps this is genuine, and the library code ought to be changed to use Float64(num)::Float64, but in this case I thought I should first report this here before trying such a "fix".

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions