# How to combine @nospecialize with type parameters?

**URL:** <https://discourse.julialang.org/t/how-to-combine-nospecialize-with-type-parameters/137304>\
**Category:** Performance\
**Tags:** parametric-methods, specializations\
**Created:** [May 27, 2026, 11:31pm UTC](https://discourse.julialang.org/t/how-to-combine-nospecialize-with-type-parameters/137304 "2026-05-27T23:31:00Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![matthias314](https://avatars.discourse-cdn.com/v4/letter/m/a88e4f/32.png) [@matthias314](https://discourse.julialang.org/u/matthias314)\
**Post date:** [May 27, 2026, 11:31pm UTC](https://discourse.julialang.org/t/how-to-combine-nospecialize-with-type-parameters/137304/1 "2026-05-27T23:31:00Z")

</div>

It seems that type parameters in functions prevent `@nospecialize` from having an effect:

```julia-auto
julia> f(@nospecialize x::T) where T = 0;

julia> f(1); f(1.0);

julia> m = only(methods(f)); m.specializations |> collect
7-element Vector{Any}:
 MethodInstance for f(::Int64)
 MethodInstance for f(::Float64)
 nothing
 nothing
 nothing
 nothing
 nothing

```

Is there a way to get around this? In the example above, one could write

```julia-auto
f(@nospecialize x::T where T) = 0

```

or drop the `T` altogether. However, what about methods where the type parameter occurs in several arguments, as in

```julia-auto
f(x::T, y::T) where T = 0

```

---

<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:** [May 28, 2026, 1:01am UTC](https://discourse.julialang.org/t/how-to-combine-nospecialize-with-type-parameters/137304/2 "2026-05-28T01:01:35Z")

</div>

So far, method parameters are always specialized in the compiled method, even when just named as part of the parameter sequence instead of being used in the method body:

[Function over-specialization on unused parts of types · Issue #26834 · JuliaLang/julia](https://github.com/JuliaLang/julia/issues/26834)

…or specifying a shared value of annotation parameters during dispatch.

> [@matthias314](#):
>
> `T where T`

That evaluates to `Any`. The `@nospecialize` effect you’re going for does happen with a named parametric type like `Vector{T} where T`.

---

<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:** [May 28, 2026, 1:12am UTC](https://discourse.julialang.org/t/how-to-combine-nospecialize-with-type-parameters/137304/3 "2026-05-28T01:12:32Z")

</div>

> [@matthias314](#):
>
> However, what about methods where the type parameter occurs in several arguments, as in
> 
> ```julia
> f(x::T, y::T) where T = 0
> 
> ```

The method static parameter may be eliminated from that particular example like so:

```julia
f((x, y)::(Vararg{T, 2} where {T})) = 0

```

AFK, did not test the above. In principle it should work.

---

<div class="post-metadata">

**Author:** ![matthias314](https://avatars.discourse-cdn.com/v4/letter/m/a88e4f/32.png) [@matthias314](https://discourse.julialang.org/u/matthias314)\
**Post date:** [May 28, 2026, 1:24am UTC](https://discourse.julialang.org/t/how-to-combine-nospecialize-with-type-parameters/137304/4 "2026-05-28T01:24:05Z")

</div>

> [@nsajko](#):
>
> `f((x, y)::(Vararg{T, 2} where {T})) = 0`

That’s a valid definition (interesting!). I’ve tried it out: when combined `@nospecialize` it specializes like a method with a type parameter. (Since `@nospecialize` doesn’t like the `(x, y)`, it has to be put at the beginning of the function body.)

---

<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:** [May 28, 2026, 4:53am UTC](https://discourse.julialang.org/t/how-to-combine-nospecialize-with-type-parameters/137304/5 "2026-05-28T04:53:27Z")

</div>

It doesn’t work, very unintuitively. I guess `Vararg` isn’t a normal type?

```julia-auto
julia> k((x, y)::(Vararg{T, 2} where {T})) = 0
k (generic function with 1 method)

julia> methods(k)
# 1 method for generic function "k" from Main:
 [1] k(::Vararg{Any, 2})
     @ REPL[46]:1

julia> k(1, 2.0)
0

julia> Vararg{T, 2} where {T}
Vararg{Any, 2}

julia> Tuple{Vararg{T, 2} where {T}}
Tuple{Any, Any}

julia> NTuple{2, T} where {T}
Tuple{T, T} where T

```

---

<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:** [May 28, 2026, 8:47am UTC](https://discourse.julialang.org/t/how-to-combine-nospecialize-with-type-parameters/137304/6 "2026-05-28T08:47:50Z")

</div>

I recently incurred into a similar issue, I needed a way to optionally specialize a function depending on a preference. I need to keep the type parameters around because the split is between when the package is loaded for trimming/compiled and when loaded in a dynamic environment. I could just rely on precompilation, but I am dealing with monster tuple types so the compiler overspecializes on every single type.  
A (very hackish) solution I’ve landed on for now is having a `@autospecialize x f(x::T) where T = 0` macro, that if you turn specialization on, it’s an identity, but if you turn it off it rewrites the function signature and removes all return types annotations and `where` parameters associated with the declared arguments.  
To keep access to the type parameters it just moves them into the preamble for them to be a runtime value instead.

It’s not generic and you kind of have to write the function signatures taking into account the limitations

I really do wish there was a better system though for telling the compiler “this type parameter can be checked at runtime, don’t specialize on it”

---

<div class="post-metadata">

**Author:** ![matthias314](https://avatars.discourse-cdn.com/v4/letter/m/a88e4f/32.png) [@matthias314](https://discourse.julialang.org/u/matthias314)\
**Post date:** [May 28, 2026, 11:29am UTC](https://discourse.julialang.org/t/how-to-combine-nospecialize-with-type-parameters/137304/7 "2026-05-28T11:29:20Z")

</div>

I conclude that the answer is what @Benny said above:

> [@Benny](#):
>
> method parameters are always specialized in the compiled method

and there seems to be no way around it.
