# Specialization on vararg of types

**URL:** <https://discourse.julialang.org/t/specialization-on-vararg-of-types/108251>\
**Category:** General Usage\
**Tags:** question\
**Created:** [January 2, 2024, 9:18am UTC](https://discourse.julialang.org/t/specialization-on-vararg-of-types/108251 "2024-01-02T09:18:41Z")\
**Posts on this page:** 1\
**Showing post:** 7

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [January 2, 2024, 1:05pm UTC](https://discourse.julialang.org/t/specialization-on-vararg-of-types/108251/7 "2024-01-02T13:05:42Z")

</div>

> [@MilesCranmer](#):
>
> However, they say you can get around this for `Vararg`, for arbitrary types with `Vararg{Any,N} where N`:

I don’t know if it was left out for some good reason, but the `Vararg` section is actually pretty vague about what is being specialized. Unlike lone functions and types, `Vararg` specifies multiple types with a possibly fixed arity. From what I could tell (though you should probably verify yourself), the “nonspecializing” `__(x::Int...)` specializes on `Int` just fine, it’s the arity it gives up on. Even `__(x...)` specializes on the first argument’s type in 2 specializations, one where the rest of the types match, and one where they are `Any` (or whatever abstract type annotates x). Making a method parameter `__(x::T...) where T` specializes on arguments matching 1 concrete type (and does not specialize on arity); this also specializes on input types like `Type{Float32}` already. Specifying the arity parameter, usually `N`, specializes over arity and every argument’s type.

That is, _except_ for types themselves as inputs, which I still don’t understand. If consistent with non-type inputs, specializations should show their concrete types `DataType` (most types), `Union` (unions), `UnionAll` (iterated unions of parametric types), not the abstract `Type`. You say it doesn’t specialize, and for good reason, but it’s certainly not falling back to `Any` for the 2nd argument onward, either. It’s more like it specializes, but weirdly. `Vararg{Type,N}` doesn’t change anything because there’s no method parameter for type selection.

danielwe’s solution performs the type selection pattern for unlimited arguments in an unintuitive and creative way. It can be written fully as `f_vararg(t::Vararg{Type{S} where S<:T}) where {T}`, so it makes sense that each selected type `S` is a subtype of the 1 method parameter `T<:Any`. This also specializes over arity despite not specifying a method parameter for it, so this is indeed the equivalent to `h_vararg(x::Vararg{Any, N}) where {N}` for non-type inputs.

Other equivalents for completion:

- `__(t::Vararg{Type{Int}})` specifies a type but does not specialize on arity, like `__(x::Int...)` for non-type inputs.
- no equivalents to `__(x::T...) where T` or `__(x...)` because a lone method parameter for the type also specializes on arity. Weird how `x::T...` didn’t specialize on arity too, but maybe the syntax mattered.
- `__(t::Vararg{Type{Int}, N}) where N` specializes on arity and the specified type, like `__(x::Vararg{Int, N}) where N` for non-type inputs.
- `__(t::Vararg{Type{T}}) where {T}` specializes on arity and 1 matching type, like `__(x::Vararg{T,N}) where {T,N}`, which also handles input types already.

> [@aplavin](#):
>
> `# specializes and generally works, but T is not defined`

In the vast majority of cases, a method parameter must be 1 known instance at compile-time for dispatch to work, even if it is absent from the body. I suppose an exception was spotted finally. Example below of the usual case:

```julia-auto
julia> myeltype(::Type{S} where {S<:AbstractArray{T,N} where N}) where {T} = 42
myeltype (generic function with 1 method)

julia> myeltype(Union{Vector{Int}, Matrix{Int}}) # T is Int
42

julia> myeltype(Union{Vector{Int}, Vector{Bool}}) # T is unspecific
ERROR: MethodError: no method matching myeltype(::Type{Union{Vector{Bool}, Vector{Int64}}})

```

For posterity since this sort of compiler stuff might be version-dependent, this was all done on v1.10.0

---

_[View the full topic](https://discourse.julialang.org/t/specialization-on-vararg-of-types/108251)._
