See a85476b and 005197a and comments therein.
In summary, dispatch on a parametric type whose type is restricted in the declaration (type A{T<:Integer} etc.) make a difference between A, A{T} and A{T<:Integer}. In one case, A{T} seems to be taken as more general than A; in another case, A seems to be taken as more general than A{T<:Integer} - see examples below.
Example: this shows the ambiguity
julia> type A{T<:Integer} <: Real
a::T
end
julia> type B <: FloatingPoint
end
julia> tst{T<:FloatingPoint,S}(::Type{T}, x::A{S}) = println(1)
tst (generic function with 1 method)
julia> tst(::Type{B}, x::A) = println(2) # this should disambiguate between the one above and the one below
tst (generic function with 2 methods)
julia> tst(::Type{B}, x::Real) = println(2)
Warning: New definition
tst(Type{B},Real) at none:1
is ambiguous with:
tst(Type{T<:FloatingPoint},A{S}) at none:1.
To fix, define
tst(Type{B},A{S})
before the new definition.
tst (generic function with 3 methods)
julia> tst(B, A(1)) # works
2
Currently, the workarounds for the example above are: defining the disambiguation method with an otherwise useless parameter
julia> type A{T<:Integer} <: Real
a::T
end
julia> type B <: FloatingPoint
end
julia> tst{T<:FloatingPoint,S}(::Type{T}, x::A{S}) = println(1)
tst (generic function with 1 method)
julia> tst{S}(::Type{B}, x::A{S}) = println(2) # useless parameter S
tst (generic function with 2 methods)
julia> tst(::Type{B}, x::Real) = println(2) # no warning though
tst (generic function with 3 methods)
julia> tst(B, A(1))
2
Or restricting the first method to S<:Integer:
julia> type A{T<:Integer} <: Real
a::T
end
julia> type B <: FloatingPoint
end
julia> tst{T<:FloatingPoint,S<:Integer}(::Type{T}, x::A{S}) = println(1) # the <:Integer part should be implicit
tst (generic function with 1 method)
julia> tst(::Type{B}, x::A) = println(2)
tst (generic function with 2 methods)
julia> tst(::Type{B}, x::Real) = println(2)
tst (generic function with 3 methods)
julia> tst(B, A(1))
2
One more problem: from the last example, continue like this:
julia> tst(::Type{FloatingPoint}, x::A) = println(3) # this should be more specific then the one which prints 1
tst (generic function with 4 methods)
julia> tst(FloatingPoint, A(1)) # calls the wrong version
1
Again, to fix it restrict the type parameter in the above definition:
julia> tst{S<:Integer}(::Type{FloatingPoint}, x::A{S}) = println(3)
tst (generic function with 4 methods)
julia> tst(FloatingPoint, A(1))
3
See a85476b and 005197a and comments therein.
In summary, dispatch on a parametric type whose type is restricted in the declaration (
type A{T<:Integer}etc.) make a difference betweenA,A{T}andA{T<:Integer}. In one case,A{T}seems to be taken as more general thanA; in another case,Aseems to be taken as more general thanA{T<:Integer}- see examples below.Example: this shows the ambiguity
Currently, the workarounds for the example above are: defining the disambiguation method with an otherwise useless parameter
Or restricting the first method to
S<:Integer:One more problem: from the last example, continue like this:
Again, to fix it restrict the type parameter in the above definition: