# Parametric method type matching issue

**URL:** <https://discourse.julialang.org/t/parametric-method-type-matching-issue/24383>\
**Category:** Internals & Design\
**Created:** [May 19, 2019, 6:51pm UTC](https://discourse.julialang.org/t/parametric-method-type-matching-issue/24383 "2019-05-19T18:51:18Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![tk3369](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tk3369/32/2824_2.png) [@tk3369](https://discourse.julialang.org/u/tk3369)\
**Post date:** [May 19, 2019, 6:51pm UTC](https://discourse.julialang.org/t/parametric-method-type-matching-issue/24383/1 "2019-05-19T18:51:18Z")

</div>

Consider this function

```julia
foo(x::T, y::S) where {T <: Integer, S <: T} = 1

```

I read it as

1. `y` has a type of `S`
2. type `S` should be a subtype of `T`
3. type `T` should be a subtype of `Integer`

But, I can do

```julia
julia> foo(1, 0x00)
1

```

`T` is `Int64`, `S` is `UInt8`, but `S` is not a subtype of `T`. So, why would it dispatch? It seems that it’s enforcing `S` to be a subtype of `Integer` rather than a subtype of `T`.

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [May 19, 2019, 6:59pm UTC](https://discourse.julialang.org/t/parametric-method-type-matching-issue/24383/2 "2019-05-19T18:59:50Z")

</div>

What would be a subtype of `T`? If `T` is concrete there are no subtypes apart from `T` itself.

---

<div class="post-metadata">

**Author:** ![tk3369](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tk3369/32/2824_2.png) [@tk3369](https://discourse.julialang.org/u/tk3369)\
**Post date:** [May 19, 2019, 7:02pm UTC](https://discourse.julialang.org/t/parametric-method-type-matching-issue/24383/3 "2019-05-19T19:02:08Z")

</div>

Yes, that would be the behavior that I expect i.e. `S == T`, when `T` is concrete.

Technically, `Union{}` or `Base.Bottom` is the bottom type for all types but that not useful in this context.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [May 19, 2019, 7:02pm UTC](https://discourse.julialang.org/t/parametric-method-type-matching-issue/24383/4 "2019-05-19T19:02:12Z")

</div>

> [@tk3369](#):
>
> `T` is `Int64`

No. T is undefined.

---

<div class="post-metadata">

**Author:** ![tk3369](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tk3369/32/2824_2.png) [@tk3369](https://discourse.julialang.org/u/tk3369)\
**Post date:** [May 19, 2019, 7:03pm UTC](https://discourse.julialang.org/t/parametric-method-type-matching-issue/24383/5 "2019-05-19T19:03:11Z")

</div>

> [@yuyichao](#):
>
> No. T is undefined.

`T` is known when the method is called. Isn’t it dynamic?

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [May 19, 2019, 7:05pm UTC](https://discourse.julialang.org/t/parametric-method-type-matching-issue/24383/6 "2019-05-19T19:05:31Z")

</div>

> [@tk3369](#):
>
> `T` is known when the method is called

No. There are infinite number of `T` that can match so `T` is not known at any time.

```julia
julia> foo(x::T, y::S) where {T <: Integer, S <: T} = (T, S)
foo (generic function with 1 method)

julia> foo(1, 0x00)
ERROR: UndefVarError: T not defined
Stacktrace:
 [1] foo(::Int64, ::UInt8) at ./REPL[1]:1
 [2] top-level scope at none:0

```

> [@tk3369](#):
>
> Isn’t it dynamic?

What does this mean?

---

<div class="post-metadata">

**Author:** ![tk3369](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tk3369/32/2824_2.png) [@tk3369](https://discourse.julialang.org/u/tk3369)\
**Post date:** [May 19, 2019, 7:14pm UTC](https://discourse.julialang.org/t/parametric-method-type-matching-issue/24383/7 "2019-05-19T19:14:39Z")

</div>

At the call site, I’m passing two arguments and they have type `Int64` and `UInt8` respectively. If I just match them to `foo`’s signature then `T` would be `Int64` and `S` would be `UInt8`, except that it does not satisfy the where condition properly because `Int64 <: Integer` but `UInt8 <: Int64` is not true.

I see that `T` is not defined in your example above but I don’t understand why it complains about that. Can you elaborate why there are _infinite number_ of `T` that can match?

When I said dynamic, I was just referring to dynamic dispatch where at runtime the types of all arguments are known.

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [May 19, 2019, 7:21pm UTC](https://discourse.julialang.org/t/parametric-method-type-matching-issue/24383/8 "2019-05-19T19:21:45Z")

</div>

> [@yuyichao](#):
>
> ```julia
> julia> foo(x::T, y::S) where {T <: Integer, S <: T} = (T, S)
> foo (generic function with 1 method)
> 
> julia> foo(1, 0x00)
> ERROR: UndefVarError: T not defined
> Stacktrace:
> [1] foo(::Int64, ::UInt8) at ./REPL[1]:1
> [2] top-level scope at none:0
> 
> ```

But

```julia
julia> foo(x::T, y::S) where {T <: Integer, S <: T} = (T, S)
foo (generic function with 1 method)

julia> foo(1,1)
(Int64, Int64)

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [May 19, 2019, 7:28pm UTC](https://discourse.julialang.org/t/parametric-method-type-matching-issue/24383/9 "2019-05-19T19:28:08Z")

</div>

> [@tk3369](#):
>
> then `T` would be `Int64` and `S` would be `UInt8`

No `T` could be anything that is a supertype of `Int64` and `S` could be anything that is a supertype of `UInt8`, there are infinite many of those.

It’s the same reason `f(::T, ::Vector{T}) where T` can be called with `f(1, [])`. You can’t say in this case that you first match the `::T` to `T = Int` since that’ll conflict with the `::Vector{T}`. In this case `T = Any` in the end.

> [@tk3369](#):
>
> I see that `T` is not defined in your example above but I don’t understand why it complains about that. Can you elaborate why there are _infinite number_ of `T` that can match?

Because there are infinite number of types that is supertype of `Int64`.

I believe you are confused about the special rule about covariant type parameters. I don’t know what’s the exact definition of the rule right now (in corner cases, like when `x` and `y` have the same time shown in @giordano’s post ) but it says that if a type parameter only appears in covariant location then it must be a concrete type. This is so that `(::T, ::T) where T` won’t be the same as `(::Any, ::Any)` and `(::Tuple{T,T}) where T` won’t be the same as `(::Tuple{Any,Any})`. The rule does not apply since you are using the type parameter elsewhere in this case.

> [@tk3369](#):
>
> When I said dynamic, I was just referring to dynamic dispatch where at runtime the types of all arguments are known.

1. Dynamic dispatch means the dispatch is done at runtime, it’s in contrast to static dispatch and both are purely optimization concept and has nothing to do with the semantics. In fact, if not for all your calls are in the global scope, the dispatch is certainly going to be static.
2. The types of the argument of course must be know by dispatch time (which must be no latter than runtime) but that does not mean anything about type parameters. They don’t need to be assigned.

---

<div class="post-metadata">

**Author:** ![tk3369](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tk3369/32/2824_2.png) [@tk3369](https://discourse.julialang.org/u/tk3369)\
**Post date:** [May 19, 2019, 9:15pm UTC](https://discourse.julialang.org/t/parametric-method-type-matching-issue/24383/10 "2019-05-19T21:15:01Z")

</div>

Thanks for the additional details. I have found the documentation about [Diagonal Types](https://docs.julialang.org/en/v1/devdocs/types/index.html#Diagonal-types-1) and it has cleared up some of my misunderstanding.

How about this? Even though `T` is undefined, `S` is determined to be `UInt8`… what makes it possible to return `S` here?

```julia
julia> goo(x::T, y::S) where {T <: Integer, S <: T} = S
goo (generic function with 1 method)

julia> goo(1, 0x00)
UInt8

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [May 19, 2019, 11:47pm UTC](https://discourse.julialang.org/t/parametric-method-type-matching-issue/24383/11 "2019-05-19T23:47:39Z")

</div>

Because S can only be a concrete type here
