Experimenting with world age and ran into a weird thing. This is the session that makes sense:
julia> function evalbad(i)
ex = :(globali() = $i)
eval(ex) # evaluates new global method at runtime
globali() # compiles method existing at compile-time
end
evalbad (generic function with 1 method)
julia> globali() = 1
globali (generic function with 1 method)
julia> map([Bool, Int32, Int64, Float32, Float64, ComplexF64, String]) do i
Base.return_types(evalbad, Tuple{i})[1] end |> println
DataType[Int64, Int64, Int64, Int64, Int64, Int64, Int64]
But in a session where the world-age-issue method defined the global method, Base.return_types
fails for Int64
specifically. Test.@inferred
then also fails for that input (didn’t try other inputs because it would execute the call). @code_warntype
works; Test.@inferred
only works after the @code_warntype
; Base.return_types
only works after both @code_warntype
and Test.@inferred
. I knew that reflection can diverge from actually compiled code because of incorrect assumptions of input type specialization, but this seems different because of the diverging side effects, like type inference isn’t one algorithm.
julia> function evalbad(i)
ex = :(globali() = $i)
eval(ex) # evaluates new global method at runtime
globali() # compiles method existing at compile-time
end
evalbad (generic function with 1 method)
julia> evalbad(1)
ERROR: MethodError: no method matching globali()
The applicable method may be too new: running in world age...
julia> globali() # definitely exists
1
julia> map([Bool, Int32, Int64, Float32, Float64, ComplexF64, String]) do i
Base.return_types(evalbad, Tuple{i})[1] end |> println
DataType[Int64, Int64, Any, Int64, Int64, Int64, Int64]
julia> using Test; @inferred evalbad(2)
ERROR: return type Int64 does not match inferred return type Any...
julia> @inferred evalbad(3)
ERROR: return type Int64 does not match inferred return type Any...
julia> @code_warntype evalbad(4)
MethodInstance for evalbad(::Int64)
...
Body::Int64
...
│ %5 = Main.globali()::Core.Const(3)
...
julia> map([Bool, Int32, Int64, Float32, Float64, ComplexF64, String]) do i
Base.return_types(evalbad, Tuple{i})[1] end |> println
DataType[Int64, Int64, Any, Int64, Int64, Int64, Int64]
julia> @inferred evalbad(5) # now it works
3
julia> map([Bool, Int32, Int64, Float32, Float64, ComplexF64, String]) do i
Base.return_types(evalbad, Tuple{i})[1] end |> println
DataType[Int64, Int64, Int64, Int64, Int64, Int64, Int64]
On v1.10.3.