julia> f1(argL::T, argR::T) where {T} = 1
f1 (generic function with 1 method)
julia> f1(argL::T1, argR::T2) where {T, T1<:AbstractArray{T}, T2<:AbstractArray{T}} = 2
f1 (generic function with 2 methods)
julia> f1([1], [1])
2
Shouldn’t f1([1], [1]) throw a MethodError since neither method is more specific than the other (i.e., the set of argument types of one method is a proper subset of another) when the input argument types are (::T, ::T) where T==Vector{Int}?
I would imagine that one needs to implement the following method to avoid the ambiguity:
The implementation thinks otherwise. I think Julia just weighs the T<:Any before whether arguments share a type via a static parameter.
julia> methods(f1)
# 2 methods for generic function "f1" from Main:
[1] f1(argL::T1, argR::T2) where {T, T1<:(AbstractArray{T}), T2<:(AbstractArray{T})}
@ REPL[2]:1
[2] f1(argL::T, argR::T) where T
@ REPL[1]:1
julia> Base.morespecific(methods(f1)...)
true
julia> invoke(f1, Tuple{T, T} where T, [1], [1]) # checking the other method works
1
It flips if you restricted T<:AbstractArray, of course.
julia> methods(f2)
# 2 methods for generic function "f2" from Main:
[1] f2(argL::T, argR::T) where T<:AbstractArray
@ REPL[8]:1
[2] f2(argL::T1, argR::T2) where {T, T1<:(AbstractArray{T}), T2<:(AbstractArray{T})}
@ REPL[9]:1
julia> Base.morespecific(methods(f2)...)
true