# Need help understanding Type parameters and Vararg tuples

**URL:** <https://discourse.julialang.org/t/need-help-understanding-type-parameters-and-vararg-tuples/122683>\
**Category:** General Usage\
**Created:** [November 15, 2024, 2:51pm UTC](https://discourse.julialang.org/t/need-help-understanding-type-parameters-and-vararg-tuples/122683 "2024-11-15T14:51:37Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![cshen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cshen/32/217287_2.png) [@cshen](https://discourse.julialang.org/u/cshen)\
**Post date:** [November 15, 2024, 2:51pm UTC](https://discourse.julialang.org/t/need-help-understanding-type-parameters-and-vararg-tuples/122683/1 "2024-11-15T14:51:37Z")

</div>

Hello!

I’m encountering quite an headscratcher, I’ve given it quite some time but I couldn’t crack. I am struggling to understand why a tuple of two types is not being recognized as such, while all the intermediate steps are successfull.

Here is a MWE

```julia
abstract type A end
abstract type B end
abstract type C{TA<:A, TB<:B} end

struct a <: A end
struct b <: B end
struct c1{TA <: A, TB <: B} <: C{TA, TB}
	ta::TA
	tb::TB
	e::Int
end
struct c2{TA<: A, TB <: B} <: C{TA, TB} 
	ta::TA
	tb::TB
	e::Float 
end

e1 = c1(a(), b(), 1)
e2 = c2(a(), b(), 1.0)

e1 isa TC where {TA <: A, TB <: B, TC <: C{TA, TB}}
# -> true
e2 isa TC where {TA <: A, TB <: B, TC <: C{TA, TB}} 
# -> true
# great!, then i can do
(e1, e2) isa Tuple{Vararg{<: C{TA, TB}}} where {TA <: A, TB <: B} 
# -> true

# therefore also
(e1, e2) isa Tuple{Vararg{TC}} where {TA <: A, TB <: B, TC <: C{TA, TB}} 
# -> false (???) huh?

#but
[e1, e2] isa Vector{TC} where {TA <: A, TB <: B, TC <: C{TA, TB}} 
# -> true

```

I’ve read the manual on types multiple times but for the life of me I couldn’t understand what is going on here. Why is that second to last test false??

---

<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:** [November 15, 2024, 4:04pm UTC](https://discourse.julialang.org/t/need-help-understanding-type-parameters-and-vararg-tuples/122683/2 "2024-11-15T16:04:35Z")

</div>

I think this is the diagonal rule?

> It turns out that being able to dispatch on whether two values have the same type is very useful (this is used by the promotion system for example), so we have multiple reasons to want a different interpretation of `Tuple{T,T} where T`. To make this work we add the following rule to subtyping: if a variable occurs more than once in covariant position, it is restricted to ranging over only concrete types. (“Covariant position” means that only `Tuple` and `Union` types occur between an occurrence of a variable and the `UnionAll` type that introduces it.) Such variables are called “diagonal variables” or “concrete variables”.  
> [More about types · The Julia Language](https://docs.julialang.org/en/v1/devdocs/types/#Diagonal-types)

It’s not about `Vararg`, but about using the the same type variable in more than one place (which I think `Vararg` implicitly does):

```julia
julia> (e1,e2) isa Tuple{TC,TC} where {TC <: C}
false

julia> (e1,e2) isa Tuple{TC, <:TC} where {TC <: C}
true

julia> (e1,e2) isa Tuple{TC,TD} where {TC <: C, TD <: C}
true

```

---

<div class="post-metadata">

**Author:** ![cshen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cshen/32/217287_2.png) [@cshen](https://discourse.julialang.org/u/cshen)\
**Post date:** [November 15, 2024, 5:23pm UTC](https://discourse.julialang.org/t/need-help-understanding-type-parameters-and-vararg-tuples/122683/3 "2024-11-15T17:23:59Z")

</div>

Thanks a million!  
Didn’t think of checking the “internals” section of the manual.  
After reading that section I must admit I didn’t completely understand it all  
but I understood enough to come up with

```julia
(e1, e2) isa Tuple{Vararg{TC} where TC} where {TA <: A, TB <: B, TC <: C{TA, TB}}
# -> true

```

hoping that this `Vararg{TC} where TC` doesn’t introduce any extra edge case!

If I understood this correctly that extra `where TC` is making all the `TC`s in the `Vararg` bound to a single variable in covariant position which makes it possible to range also over non concrete types, such as `C{TA <: A, TB <: B}`, is this correct?

---

<div class="post-metadata">

**Author:** ![cshen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cshen/32/217287_2.png) [@cshen](https://discourse.julialang.org/u/cshen)\
**Post date:** [November 16, 2024, 12:51pm UTC](https://discourse.julialang.org/t/need-help-understanding-type-parameters-and-vararg-tuples/122683/4 "2024-11-16T12:51:51Z")

</div>

Uhm, No.  
`Tuple{Vararg{G} where G}` works in the `isa` expression but when used in a function declaration or struct it complains.  
Why is that?
