On nightly:
julia> f(x) = x > 3 ? x : nothing
f (generic function with 1 method)
julia> g(imax) = [f(i) for i in 1:imax]
g (generic function with 1 method)
julia> @code_warntype g(5)
MethodInstance for g(::Int64)
from g(imax) in Main at REPL[7]:1
Arguments
#self#::Core.Const(g)
imax::Int64
Locals
#5::var"#5#6"
Body::Union{Vector{Nothing}, Vector{Union{Nothing, Int64}}, Vector{Int64}}
1 ─ (#5 = %new(Main.:(var"#5#6")))
│ %2 = #5::Core.Const(var"#5#6"())
│ %3 = (1:imax)::Core.PartialStruct(UnitRange{Int64}, Any[Core.Const(1), Int64])
│ %4 = Base.Generator(%2, %3)::Core.PartialStruct(Base.Generator{UnitRange{Int64}, var"#5#6"}, Any[Core.Const(var"#5#6"()), Core.PartialStruct(UnitRange{Int64}, Any[Core.Const(1), Int64])])
│ %5 = Base.collect(%4)::Union{Vector{Nothing}, Vector{Union{Nothing, Int64}}, Vector{Int64}}
└── return %5
The return type here may be chosen to be Vector{Union{Nothing, Int}}
instead of the union of types. I wonder if this is intentional, expecting union splitting in downstream usage? Or is this something that may be improved upon?