-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Description
In my ongoing, intermittent quest to understand Julia's precise definition of "most specific method", I found this anomaly in Julia 0.3 installed May 17:
ba = trues(3)
@which ba / ba
/(A::Union(AbstractArray{T,2},AbstractArray{T,1}),
B::Union(AbstractArray{T,2},AbstractArray{T,1})) at linalg/generic.jl:225
It should be the method /(A::BitArray{N},B::BitArray{N}) at bitarray.jl:885, which is more specific according to jl_args_morespecific().
I don't know my way around the internals of Julia real well, but I think jl_method_list_insert() is putting the generic.jl:225 method at the wrong place because it is thought to be more specific than the method /{T<:Number}(x::T<:Number,y::T<:Number) at promotion.jl:191. But, obviously, those two methods have disjoint signatures. Julia's method dispatch mechanism fundamentally depends on the more specific relation being transitive, but it's only transitive if it's always false for disjoint signatures, I think.
Here's a simple test case which does not even depend on the loop at the end of jl_method_list_insert():
f{T<:Number}(::T) = 1
f(::BitArray) = 2
f(::AbstractVecOrMat) = 3
f(ba) # returns 3, should be 2
But if I define the methods in a different order:
g(::BitArray) = 2
g(::AbstractVecOrMat) = 3
g{T<:Number}(::T) = 1
g(ba) # returns 2 as expected
But surely in the absence of ambiguity warnings the result of method dispatch should not depend on the order of definition of methods. So there must be a bug somewhere.