# What is the partial order used for multiple dispatch?

**URL:** <https://discourse.julialang.org/t/what-is-the-partial-order-used-for-multiple-dispatch/131911>\
**Category:** General Usage\
**Tags:** question, multiple-dispatch\
**Created:** [August 28, 2025, 1:41pm UTC](https://discourse.julialang.org/t/what-is-the-partial-order-used-for-multiple-dispatch/131911 "2025-08-28T13:41:06Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![rveltz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rveltz/32/2707_2.png) [@rveltz](https://discourse.julialang.org/u/rveltz)\
**Post date:** [August 28, 2025, 1:41pm UTC](https://discourse.julialang.org/t/what-is-the-partial-order-used-for-multiple-dispatch/131911/1 "2025-08-28T13:41:06Z")

</div>

In the docs, one can find that a [paragraph](https://docs.julialang.org/en/v1/manual/methods/#Iterated-dispatch) on multiple dispatch but the dispatching algorithm is not described.

My question is: given two tuples `args1, args2` of arguments (or types), what is the partial order \< which is used to compare `args1, args2` in order to select the “correct” function call (Jeff’s thesis?). I guess, when `args1, args2` are uncomparable for \<, the algo return a method ambiguity error.

This is a seemingly simple question but it never crossed my mind despite the fact that I use multiple dispatch seemingly ! Could the algo fail to find the “best” method? For example using (`+(::Matrix, ::Matrix)` instead of `+(::Symmetric, ::Symmetric)` (very bad example but you get the gist).

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [August 28, 2025, 1:48pm UTC](https://discourse.julialang.org/t/what-is-the-partial-order-used-for-multiple-dispatch/131911/2 "2025-08-28T13:48:36Z")

</div>

I think the definitive documentation is the source code:

> <https://github.com/JuliaLang/julia/blob/master/src/subtype.c>

There is a more readable exposition here:  
[https://dl.acm.org/doi/10.1145/3276483](https://dl.acm.org/doi/10.1145/3276483)

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [August 28, 2025, 2:19pm UTC](https://discourse.julialang.org/t/what-is-the-partial-order-used-for-multiple-dispatch/131911/3 "2025-08-28T14:19:09Z")

</div>

Overall, one should dispatch to the most specific method which matches the actual arguments.

If the actual arguments have type `A` (a `Tuple` of the individual argument types), and there are method signatures `S` and `T` which both match, i.e. `A <: S` and `A <: T`, then `S` is more specific if `S <: T` but not `T <: S`. (At least that’s what I like to think…)

So, the whole thing boils down to the subtype relation `<:` described in the link above.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [August 28, 2025, 3:30pm UTC](https://discourse.julialang.org/t/what-is-the-partial-order-used-for-multiple-dispatch/131911/4 "2025-08-28T15:30:03Z")

</div>

A really good place to see this (at least to a first-order approximation) is simply `methods`! The method table is **stored** in sorted order. So Julia can just walk top-down, looking for the first method that matches (`<:`) the given args. This has gotten more complicated since I last looked — Julia needs to consider world ages, too — but it’s a good first step.

All cases that “fail” are ambiguity errors.

---

<div class="post-metadata">

**Author:** ![rveltz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rveltz/32/2707_2.png) [@rveltz](https://discourse.julialang.org/u/rveltz)\
**Post date:** [August 28, 2025, 4:00pm UTC](https://discourse.julialang.org/t/what-is-the-partial-order-used-for-multiple-dispatch/131911/5 "2025-08-28T16:00:30Z")

</div>

That’s gold remark!

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [August 28, 2025, 8:14pm UTC](https://discourse.julialang.org/t/what-is-the-partial-order-used-for-multiple-dispatch/131911/6 "2025-08-28T20:14:35Z")

</div>

Here’s a simple application of the rules. It can get quite complicated with parametric types and many arguments.

```julia-auto
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-auto
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-auto
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-auto
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}

```
