Here’s a simple application of the rules. It can get quite complicated with parametric types and many arguments.
julia> f(a::Signed, b::Integer) = "si" # Tuple{Signed, Integer}
julia> f(a::Integer, b::Signed) = "is" # Tuple{Integer, Signed}
julia> f(a::Integer, b::Integer) = "ii" # Tuple{Integer, Integer}
argument type: Tuple{Int, UInt}
matches the first and third
but the first (Tuple{Signed, Integer}
) is a subtype of the third,
so the first is more specific:
julia> Tuple{Signed, Integer} <: Tuple{Integer, Integer}
true
julia> f(1, UInt(1))
"si"
argument type: Tuple{UInt, Int}
matches the second and third.
The second is a subtype of the third, so the second is more specific:
julia> Tuple{Integer, Signed} <: Tuple{Integer, Integer}
true
julia> f(UInt(1), 1)
"is"
argument: Tuple{Int,Int}
matches all the methods.
The two first are subtypes of the third, but none of them is a subtype of the other, so there’s not a unique most specific signature.
We get an error with a suggestion of a signature which would remove the ambiguity. That is, a new signature which is a subtype of both of them:
julia> Tuple{Signed, Integer} <: Tuple{Integer, Signed}
false
julia> Tuple{Integer, Signed} <: Tuple{Signed, Integer}
false
julia> f(1,1)
ERROR: MethodError: f(::Int64, ::Int64) is ambiguous.
Candidates:
f(a::Integer, b::Signed)
@ Main REPL[2]:1
f(a::Signed, b::Integer)
@ Main REPL[1]:1
Possible fix, define
f(::Signed, ::Signed)
julia> typeintersect(Tuple{Integer, Signed}, Tuple{Signed, Integer})
Tuple{Signed, Signed}