# Difference in dispatching on Union type vs. subtype of Union type

**URL:** <https://discourse.julialang.org/t/difference-in-dispatching-on-union-type-vs-subtype-of-union-type/13889>\
**Category:** General Usage\
**Tags:** parametric-types\
**Created:** [August 22, 2018, 3:08pm UTC](https://discourse.julialang.org/t/difference-in-dispatching-on-union-type-vs-subtype-of-union-type/13889 "2018-08-22T15:08:46Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![shipengcheng1230](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shipengcheng1230/32/4089_2.png) [@shipengcheng1230](https://discourse.julialang.org/u/shipengcheng1230)\
**Post date:** [August 22, 2018, 3:08pm UTC](https://discourse.julialang.org/t/difference-in-dispatching-on-union-type-vs-subtype-of-union-type/13889/1 "2018-08-22T15:08:46Z")

</div>

Hello, I would like to dispatch on the `Union` type, if I explicitly write it down, it works:

```julia
julia> T = Union{<:Number, Ref{<:Number}}
Union{Ref{#s13} where #s13<:Number, #s12} where #s12<:Number

julia> f(x::T, y::T) = "ok"
f (generic function with 1 method)

julia> f(1, Ref(1))
"ok"

```

However, if I use the subtypeing gramma:

```julia
julia> g(x::U, y::U) where {U <: T} = "ok"
g (generic function with 1 method)

julia> g(1, Ref(1))
ERROR: MethodError: no method matching g(::Int64, ::Base.RefValue{Int64})
Closest candidates are:
  g(::U<:(Union{Ref{#s13} where #s13<:Number, #s12} where #s12<:Number), ::U<:(Union{Ref{#s13} where #s13<:Number, #s12} where #s12<:Number)) where U<:(Union{Ref{#s13} where #s13<:Number, #s12} where #s12<:Number) at REPL[8]:1
Stacktrace:
 [1] top-level scope at none:0

```

I thought both arguments should fit in the type:

```julia
julia> Ref(1)::T
Base.RefValue{Int64}(1)

julia> 1::T
1

julia> T <: T
true

```

What am I missing here? Thank you!

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 22, 2018, 3:14pm UTC](https://discourse.julialang.org/t/difference-in-dispatching-on-union-type-vs-subtype-of-union-type/13889/2 "2018-08-22T15:14:46Z")

</div>

`Ref` is not a subtype of `Union`.

```julia
julia> T = Union{<:Number, Ref{<:Number}}
Union{Ref{#s1} where #s1<:Number, #s2} where #s2<:Number

julia> Ref <: T
false

```

EDIT: ~~Not the reason, I misread.~~ Ok, it kinda is, but there’s more to it, see below.

---

<div class="post-metadata">

**Author:** ![shipengcheng1230](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shipengcheng1230/32/4089_2.png) [@shipengcheng1230](https://discourse.julialang.org/u/shipengcheng1230)\
**Post date:** [August 22, 2018, 3:22pm UTC](https://discourse.julialang.org/t/difference-in-dispatching-on-union-type-vs-subtype-of-union-type/13889/3 "2018-08-22T15:22:21Z")

</div>

But what I am passing is a `Ref{Int}`, which should be a subtype of my `Union` according to the covariance:

```julia
julia> T = Union{<:Number, Ref{<:Number}}
Union{Ref{#s13} where #s13<:Number, #s12} where #s12<:Number

julia> typeof(Ref(1)) <: T
true

```

---

<div class="post-metadata">

**Author:** ![ExpandingMan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/expandingman/32/866_2.png) [@ExpandingMan](https://discourse.julialang.org/u/ExpandingMan)\
**Post date:** [August 22, 2018, 3:25pm UTC](https://discourse.julialang.org/t/difference-in-dispatching-on-union-type-vs-subtype-of-union-type/13889/4 "2018-08-22T15:25:00Z")

</div>

By writing

```julia
g(x::U, y::U)

```

you are making an assertion that `x` and `y` are of the same type (`U`).

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [August 22, 2018, 3:25pm UTC](https://discourse.julialang.org/t/difference-in-dispatching-on-union-type-vs-subtype-of-union-type/13889/5 "2018-08-22T15:25:39Z")

</div>

This is the diagonal rule (should be mentioned in the manual):

```julia
f(x::T, y::T) where T = 1

```

only ever works if `typeof(x)==typeof(y)`. Only after this check a possible subtype check on `T` is done. Example:

```julia
julia> f(x::T, y::T) where T<:Integer = 1                                                                                                                               
f (generic function with 1 method)                                                                                                                                      

julia> f(5,6)                                                                                                                                                           
1                                                                                                                                                                       
                                                                                                                                                                        
julia> f(5,UInt(6))                                                                                                                                                     
ERROR: MethodError: no method matching f(::Int64, ::UInt64)                                                                                                             
Closest candidates are:
  f(::T<:Integer, ::T<:Integer) where T<:Integer at REPL[1]:1                                                                                                           
Stacktrace:                                                                                                                                                             
 [1] top-level scope at none:0                                                                                                                                          

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 22, 2018, 3:26pm UTC](https://discourse.julialang.org/t/difference-in-dispatching-on-union-type-vs-subtype-of-union-type/13889/6 "2018-08-22T15:26:16Z")

</div>

> [@ExpandingMan](#):
>
> you are making an assertion that `x` and `y` are of the same type ( `U` ).

Indeed:

```julia
julia> g(x::H, y::G) where {G <: T, H <: T} = "ok"
g (generic function with 1 methods)

julia> g(1, Ref(1))
"ok"

```

---

<div class="post-metadata">

**Author:** ![shipengcheng1230](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shipengcheng1230/32/4089_2.png) [@shipengcheng1230](https://discourse.julialang.org/u/shipengcheng1230)\
**Post date:** [August 22, 2018, 3:37pm UTC](https://discourse.julialang.org/t/difference-in-dispatching-on-union-type-vs-subtype-of-union-type/13889/7 "2018-08-22T15:37:28Z")

</div>

Thanks everyone. I just find something in the doc about the [diagonal rule](https://docs.julialang.org/en/latest/devdocs/types/#Diagonal-types-1).
