-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Closed
Labels
bugIndicates an unexpected problem or unintended behaviorIndicates an unexpected problem or unintended behaviortypes and dispatchTypes, subtyping and method dispatchTypes, subtyping and method dispatch
Description
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
Metadata
Metadata
Assignees
Labels
bugIndicates an unexpected problem or unintended behaviorIndicates an unexpected problem or unintended behaviortypes and dispatchTypes, subtyping and method dispatchTypes, subtyping and method dispatch