# Type Instability and Union Splitting

**URL:** https://discourse.julialang.org/t/type-instability-and-union-splitting/88886
**Category:** General Usage
**Tags:** performance, type
**Created:** [October 18, 2022, 5:45am UTC](https://discourse.julialang.org/t/type-instability-and-union-splitting/88886 "2022-10-18T05:45:17Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![HashBrown](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hashbrown/32/43601_2.png) [@HashBrown](https://discourse.julialang.org/u/HashBrown)
#### Post date: [October 18, 2022, 5:45am UTC](https://discourse.julialang.org/t/type-instability-and-union-splitting/88886/1 "2022-10-18T05:45:17Z")

</div>

So I know the following code is not type stable:

```julia
foo(x::Int64, y::Float64) = x < y ? x : y

```

As a human I understand that the return type of this function must be `Union{Int64, Float64}`.

Does the compiler also understand this? In a function that calls `foo` will union splitting be used in order to make the code performant despite the type instability here?

On a related note I have noticed that `Base.iterate` is another function that falls under a similar boat. That is it returns a `Union{T, Nothing}`. Is this treated the same way, or is there something special about it?

Would explicitly declaring the return type as the appropriate `Union` help the compiler generate efficient code in either case, or is that information that the compiler determines for itself regardless?

---

<div class="post-metadata">

### Author: ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)
#### Post date: [October 18, 2022, 6:36am UTC](https://discourse.julialang.org/t/type-instability-and-union-splitting/88886/2 "2022-10-18T06:36:16Z")

</div>

> **[Union-splitting: what it is, and why you should care](https://julialang.org/blog/2018/08/union-splitting/)**
>
> Union-splitting: what it is, and why you should care | Among those who follow Julia's development closely, one of the (many) new features causing great excitement is something called

---

<div class="post-metadata">

### Author: ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)
#### Post date: [October 18, 2022, 6:37am UTC](https://discourse.julialang.org/t/type-instability-and-union-splitting/88886/3 "2022-10-18T06:37:08Z")

</div>

> [@HashBrown](#):
>
> Does the compiler also understand this? In a function that calls `foo` will union splitting be used in order to make the code performant despite the type instability here?

Yes and yes.

---

<div class="post-metadata">

### Author: ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)
#### Post date: [October 18, 2022, 6:38am UTC](https://discourse.julialang.org/t/type-instability-and-union-splitting/88886/4 "2022-10-18T06:38:32Z")

</div>

> [@HashBrown](#):
>
> Would explicitly declaring the return type as the appropriate `Union` help the compiler generate efficient code in either case, or is that information that the compiler determines for itself regardless

Typically, that’s unnecessary and doesn’t help. The compiler will figure this out by itself.

---

<div class="post-metadata">

### Author: ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)
#### Post date: [October 18, 2022, 3:23pm UTC](https://discourse.julialang.org/t/type-instability-and-union-splitting/88886/5 "2022-10-18T15:23:23Z")

</div>

A useful tool for this is `@code_warntype`

```julia
julia> @code_warntype foo(1,2.0)
MethodInstance for foo(::Int64, ::Float64)
  from foo(x::Int64, y::Float64) in Main at REPL[1]:1
Arguments
  #self#::Core.Const(foo)
  x::Int64
  y::Float64
Body::Union{Float64, Int64}
1 ─ %1 = (x < y)::Bool
└── goto #3 if not %1
2 ─ return x
3 ─ return y

```

The line `Body::Union{Float64, Int64}` indicates that Julia has determined the return type of this call to be the union you’d expect.

There are a few cases (but not this one) where `@code_warntype` will “lie” to you. It always assumes that code will fully specialize on the input types. This can lead it to indicate that things are inferred even when they may not be due to [cases where Julia avoids specialization](https://docs.julialang.org/en/v1/manual/performance-tips/#Be-aware-of-when-Julia-avoids-specializing). There might be a couple of other situations where it also gives misleading results, but this is the main hiccup I’m aware of.
