# Small union types: present and future (looking for some guidelines)

**URL:** https://discourse.julialang.org/t/small-union-types-present-and-future-looking-for-some-guidelines/6320
**Category:** Internals & Design
**Tags:** question
**Created:** [October 8, 2017, 7:37am UTC](https://discourse.julialang.org/t/small-union-types-present-and-future-looking-for-some-guidelines/6320 "2017-10-08T07:37:02Z")
**Posts on this page:** 1
**Showing post:** 2

<div class="post-metadata">

### Author: ![quinnj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/quinnj/32/11_2.png) [@quinnj](https://discourse.julialang.org/u/quinnj)
#### Post date: [October 8, 2017, 8:20am UTC](https://discourse.julialang.org/t/small-union-types-present-and-future-looking-for-some-guidelines/6320/2 "2017-10-08T08:20:28Z")

</div>

> [@Tamas\_Papp](#):
>
> what are the restrictions on n? I found that even n=3 works occasionally, n=2, reliably.

Technically, the limit is `typemax(Int8)`, but the compiler has trouble w/ “exotic” Union types; I’d say anything over 6-8, you’ll likely run into compiler issues. And what I’m talking about here is any kind of Union types, concrete, abstract, whatever.

> [@Tamas\_Papp](#):
>
> what are the restrictions on the Ts? They would of course have to be concrete types, but do they have to be bits types? Any other restrictions?

There are no restrictions on `T`s generally; unless you’re looking for the current memory optimizations available in 0.7. The memory optimizations ares:

1. Field types of “isbits-Union” are stored inline, with extra “selector” byte to indicate which type is stored in the actual field slot. This works by reserving a field slot big enough to hold the largest Union element type; so a field declared w/ a type of `Union{Void, Int8, Int64}` is going to reserve 9 bytes in the struct: the first 8 in order to hold a potential `Int64`, and the last byte to store a `Int8` value of `0`, `1`, or `2`, depending on if the _actual_ value of the field is `Void`, `Int8`, or `Int64`, respectively.
2. This same type of optimization has been implemented for Arrays of isbits-Union eltypes. For example, in 0.6, a `Vector{Union{Void, Float32}}(10)` allocated 80 bytes for elements, because Union eltypes were stored as pointers to actual values. In 0.7, that same array now allocates only 40 bytes, half as many, because the elements are now stored inline like other isbits types.

> [@Tamas\_Papp](#):
>
> The above questions are about return types, where the caller resolves the uncertainty immediately (maybe that’s why it is fast for me?) My impression is that Union types as fields or eltypes are still not recommended. Is this correct?

Yes, currently there is an [open issue](https://github.com/JuliaLang/julia/issues/23338) about performance issues w/ inferred Union return types. It currently boils down to the fact that when a `Union` type is inferred, codegen then tries to speculatively branch on the specific Union types. The problem is that the branches are inserted correctly, but within the branches, nothing ever gets inlined. This ends up causing severe performance problems if this situation happens in a hot inner loop. But as you’ve discovered, there’s a current workaround where the user has explicit code to branch on the return type anyway! In that case, inference doesn’t have to generate the Union branches, it can use them and inlines happily.

Hope that helps explain things! Let me know if anything didn’t make sense.

---

_[View the full topic](https://discourse.julialang.org/t/small-union-types-present-and-future-looking-for-some-guidelines/6320)._
