Motivation:
Imagine I want to use the return type of a function to define an output array of that type.
julia> makearray(f::Function, ::Type{T}) where T =
Core.Inference.return_type(f, (T,T))[]
makearray (generic function with 3 methods)
julia> makearray(cmp, Int)
0-element Array{Int64,1}
julia> makearray(cmp, Integer)
0-element Array{Any,1}
julia> which(cmp, (Integer, Integer))
cmp(x::Integer, y::Integer) in Base at operators.jl:348
julia> which(cmp, (Int, Int))
cmp(x::Integer, y::Integer) in Base at operators.jl:348
The result is as I expected with Int, but fails with Integer. That is due to Core..return_type.
The used method is the same in both cases:
No, inference is not broken as it correctly infers that the return type of cmp(<:Integer,<:Integer) must be a subtype of Any. But sure, there is room for improvement.
Also, note that it is discouraged to make your program dependent on inference; one of the reasons being because inference might get better in the future and your program may then fail.
I view the current situation as a conservative approach:
Also if all current implementations of cmp clearly return Int64, and also if I call invoke to get the implementation for the abstract Integer, there is no guarantee, that in the future, somebody implements for a new subtype of Integer a methods with a different return type.
But being conservative is not a typical approach for Julia, I suppose.
That does not sound like a big obstacle! I my example there are 6: method(cmp, (Integer, Integer). But in general, there is no limit, except given of the size of the code base.
For the moment, I will stick to my work-around. I force a concrete type to be used, by changing the signature to:
julia> makearray(f::Function, ::T) where T = Core.Inference.return_type(f, (T,T))[]
makearray (generic function with 1 method)
julia> makearray(cmp, BigFloat(0))
0-element Array{Int64,1}
Imagine I want to use the return type of a function to define an output array of that type.
The following describes how this is handled generally in Base to have inference-independent behavior (except for empty arrays), avoiding what @mauro3 pointed above. Granted, it won’t be generally inferable but it will give you a tight element-typed-array when not inferable.