# Dispatch differences between restricted and unrestricte type parameter

**URL:** <https://discourse.julialang.org/t/dispatch-differences-between-restricted-and-unrestricte-type-parameter/113505>\
**Category:** General Usage\
**Created:** [April 25, 2024, 2:39pm UTC](https://discourse.julialang.org/t/dispatch-differences-between-restricted-and-unrestricte-type-parameter/113505 "2024-04-25T14:39:33Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![hexaeder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hexaeder/32/24403_2.png) [@hexaeder](https://discourse.julialang.org/u/hexaeder)\
**Post date:** [April 25, 2024, 2:39pm UTC](https://discourse.julialang.org/t/dispatch-differences-between-restricted-and-unrestricte-type-parameter/113505/1 "2024-04-25T14:39:33Z")

</div>

Why is the dispatch behavior different for the following codes? The only difference is that the type parameter `T` of the abstract type is restricted (`<:Real`) in the first snippet and unrestricted in the second snippet.

```julia
abstract type Abstract{T<:Real} end
struct Concrete{T} <: Abstract{T}
    Concrete(t) = new{typeof(t)}()
end
[Concrete(1), Concrete(1.0)] isa Vector{<:Abstract} # false
[Concrete(1), Concrete(1.0)] isa Vector{<:Abstract{<:T}} where {T} # true

abstract type Abstract2{T} end
struct Concrete2{T} <: Abstract2{T}
    Concrete2(t) = new{typeof(t)}()
end
[Concrete2(1), Concrete2(1.0)] isa Vector{<:Abstract2} # true
[Concrete2(1), Concrete2(1.0)] isa Vector{<:Abstract2{<:T}} where {T} # true

```

---

<div class="post-metadata">

**Author:** ![kimikage](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kimikage/32/14534_2.png) [@kimikage](https://discourse.julialang.org/u/kimikage)\
**Post date:** [April 25, 2024, 2:52pm UTC](https://discourse.julialang.org/t/dispatch-differences-between-restricted-and-unrestricte-type-parameter/113505/2 "2024-04-25T14:52:33Z")

</div>

The following may help you understand or further confuse you.

```julia
struct Concrete1R{T<:Real} <: Abstract{T}
    Concrete1R(t) = new{typeof(t)}()
end

[Concrete1R(1), Concrete1R(1.0)] isa Vector{<:Abstract} # true
[Concrete1R(1), Concrete1R(1.0)] isa Vector{<:Abstract{<:T}} where {T} # true

```

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [April 25, 2024, 2:57pm UTC](https://discourse.julialang.org/t/dispatch-differences-between-restricted-and-unrestricte-type-parameter/113505/3 "2024-04-25T14:57:11Z")

</div>

> [@hexaeder](#):
>
> Why is the dispatch behavior different for the following codes?

It’s not dispatch, it’s the subtyping, due to the abstract type type parameter constraint not being inherited by its subtype:

```julia-repl
julia> abstract type A{T<:Real} end

julia> struct U{T} <: A{T} end

julia> struct V{T<:Real} <: A{T} end

julia> Vector{U} <: Vector{<:A}
false

julia> Vector{V} <: Vector{<:A}
true

```

> <https://github.com/JuliaLang/julia/issues/53380>
>
> \<!--
> If you have a question please search or post to our Discourse site: https:…//discourse.julialang.org.
> We use the GitHub issue tracker for bug reports and feature requests only.
> 
> If you're submitting a bug report, be sure to include as much relevant information as
> possible, including:
> 
> 1. The output of \`versioninfo()\`
> 2. How you installed Julia
> 3. A minimal working example (MWE), also known as a minimum reproducible example
> 
> If you're experiencing a problem with a particular package, open an issue on that
> package's repository instead.
> 
> Thanks for contributing to the Julia project!
> \--\>
> 
> If you have an abstract type with a constrained type parameter, subtypes whose parameters inherit from the type's parameters do not inherit the constraints.
> \`\`\`julia
> abstract type AbstractFoo{T\<:Real}
> end
> 
> struct Foo{T} \<: AbstractFoo{T} end
> \`\`\`
> 
> \`\`\`julia-repl
> julia\> supertype(Foo)
> AbstractFoo{T} where T
> 
> julia\> supertype(Foo{\<:Real}}
> AbstractFoo
> 
> julia\> Foo \<: AbstractFoo # This one is very much unexpected!
> false
> 
> julia\> Foo{\<:Real} \<: AbstractFoo
> true
> \`\`\`
> This is true even though you can't construct a type which violates the constraints on its parent's parameters:
> \`\`\`julia-repl
> julia\> Foo{String}
> ERROR: TypeError: in AbstractFoo, in T, expected T\<:Real, got Type{String}
> Stacktrace:
> \[1\] top-level scope
> @ REPL\[5\]:1
> \`\`\`
> This is a subtle point that is not included in the documentation on abstract parametric types, but has caused me some headaches when some subtype relations broke unexpectedly.
> 
> The above examples were tested on Julia 1.10 (version info below) running on Arch Linux in WSL2, installed with the AUR provided \`julia-bin\` package that provides the official release:
> \`\`\`julia-repl
> julia\> versioninfo()
> Julia Version 1.10.0
> Commit 3120989f39b (2023-12-25 18:01 UTC)
> Build Info:
> Official https://julialang.org/ release
> Platform Info:
> OS: Linux (x86\_64-linux-gnu)
> CPU: 20 × 13th Gen Intel(R) Core(TM) i5-13600K
> WORD\_SIZE: 64
> LIBM: libopenlibm
> LLVM: libLLVM-15.0.7 (ORCJIT, goldmont)
> Threads: 1 on 20 virtual cores
> \`\`\`

---

<div class="post-metadata">

**Author:** ![hexaeder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hexaeder/32/24403_2.png) [@hexaeder](https://discourse.julialang.org/u/hexaeder)\
**Post date:** [April 25, 2024, 3:06pm UTC](https://discourse.julialang.org/t/dispatch-differences-between-restricted-and-unrestricte-type-parameter/113505/4 "2024-04-25T15:06:43Z")

</div>

Thanks to both of you. I was calling it dispatch because in my original code came up when I tried to dispatch on `Vector{<:Abstract}` and it threw a `MethodError`.

I was wrongly assuming, that concrete types inherit the abstract type parameter constraint, which is why I put it there in the first place. So that I cannot construct concert subtypes violating that constraint.

Now it makes sense! Or at least I understand the rules, even though I still find them quite unintuitive. I’ll just omit the type restriction in my abstract type then.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [April 25, 2024, 3:09pm UTC](https://discourse.julialang.org/t/dispatch-differences-between-restricted-and-unrestricte-type-parameter/113505/5 "2024-04-25T15:09:28Z")

</div>

Added some labels to the Github issue so it wouldn’t be forgotten.
