# Surprising type instability in apply\_type

**URL:** <https://discourse.julialang.org/t/surprising-type-instability-in-apply-type/95655>\
**Category:** General Usage\
**Tags:** code\_warntype, type-stability\
**Created:** [March 7, 2023, 9:47am UTC](https://discourse.julialang.org/t/surprising-type-instability-in-apply-type/95655 "2023-03-07T09:47:19Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![tverho](https://avatars.discourse-cdn.com/v4/letter/t/839c29/32.png) [@tverho](https://discourse.julialang.org/u/tverho)\
**Post date:** [March 7, 2023, 9:47am UTC](https://discourse.julialang.org/t/surprising-type-instability-in-apply-type/95655/1 "2023-03-07T09:47:19Z")

</div>

It seems suprising that type inferrence doesn’t work here:

```julia
f(Tp) = Tp{Int, Int}

```

```julia
julia> f(Tuple)
Tuple{Int64, Int64}

julia> @code_warntype f(Tuple)
MethodInstance for f(::Type{Tuple})
  from f(Tp) in Main at REPL[5]:1
Arguments
  #self#::Core.Const(f)
  Tp::Type{Tuple}
Body::Any
1 ─ %1 = Core.apply_type(Tp, Main.Int, Main.Int)::Any
└── return %1

```

Seems like the compiler has all the information it needs to figure out the output type? Is this some conscious limitation to the inferrence system for performance reasons?

If the first argument to `apply_type` is a constant, inferrence works just fine, for example `g(Tp) = Tuple{Tp, Tp}`.

I’m running Julia 1.8.

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [March 7, 2023, 11:06am UTC](https://discourse.julialang.org/t/surprising-type-instability-in-apply-type/95655/2 "2023-03-07T11:06:04Z")

</div>

To pass types as arguments, I think the better (inference-compatible) way uses [type selectors](https://docs.julialang.org/en/v1/manual/types/#man-typet-type). Otherwise, the only thing we can infer statically is the _type_ of `Tuple` (which is `DataType`), and not the actual _value_ of `Tuple`, which is the type you want to use.

See here for instance:

```julia
julia> g(::Type{Tp}) where {Tp} = Tp{Int, Int}
g (generic function with 1 method)

julia> @code_warntype g(Tuple)
MethodInstance for g(::Type{Tuple})
  from g(::Type{Tp}) where Tp in Main at REPL[2]:1
Static Parameters
  Tp = Tuple
Arguments
  #self#::Core.Const(g)
  _::Type{Tuple}
Body::Type{Tuple{Int64, Int64}}
1 ─ %1 = Core.apply_type($(Expr(:static_parameter, 1)), Main.Int, Main.Int)::Core.Const(Tuple{Int64, Int64})
└── return %1

```

---

<div class="post-metadata">

**Author:** ![tverho](https://avatars.discourse-cdn.com/v4/letter/t/839c29/32.png) [@tverho](https://discourse.julialang.org/u/tverho)\
**Post date:** [March 7, 2023, 11:31am UTC](https://discourse.julialang.org/t/surprising-type-instability-in-apply-type/95655/3 "2023-03-07T11:31:22Z")

</div>

Ok that’s helpful, thanks!
