Julia doesn't box integers, that would destroy speed. It also doesn't protect from overflow/underflow. It specializes on Vector{Int} so that's it's just a standard vector of integers. Then Vector{Union{Int,Missing}} is stored in memory as a vector of integers with a bitarray declaring missings. Indexing operations are expanded to ifelse a check for the existence and then return the value if it exists or a missing. Then branches are added by the compiler to handle the small unions. This keeps pure integer use without overhead, and gives a small penalty when using missing (which doesn't turn out to be all that bad due to how pipelining is usually done), but it's safe and any type can have missing values.
Thank you. I look forward into learning more about how Julia handles this.