How is the output type determined in map and friends?

Just curious, how is the container type determined for map?

It seem pretty magical to me:

julia> @code_warntype map(x -> x/2, rand(Int, 5))
Body::Array{Float64,1}
1995 1 ─ %1 = %new(Base.Generator{Array{Int64,1},getfield(Main, Symbol("##3#4"))}, getfield(Main, Symbol("##3#4"))(), A)::Base.Generator{Array{Int64,1},getfield(Main, Symbol("##3#4"))}                    │╻╷ Type
     │   %2 = invoke Base._collect(_3::Array{Int64,1}, %1::Base.Generator{Array{Int64,1},getfield(Main, Symbol("##3#4"))}, $(QuoteNode(Base.EltypeUnknown()))::Base.EltypeUnknown, $(QuoteNode(Base.HasShape{1}()))::Base.HasShape{1})::Array{Float64,1}
     └──      return %2 

I guess it boils down to this: how is the output type of functions determined before they are evaluated in regular Julia? I understand that this is definitely something that the compiler should be able to figure out, but how would I be able to write a function that uses the compiler’s smarts to pre-allocate an output array?

It isn’t. The inference type is used for the empty case.

Don’t. Not for any non-empty case or at least not without making sure your code runs just fine without it.

Good advice to keep it simple, but it looks like the inference type is used by map. I’m just curious how it works.

julia> @code_warntype map(x -> x/2, rand(Int, 0))
Body::Array{Float64,1}
1995 1 ─ %1 = %new(Base.Generator{Array{Int64,1},getfield(Main, Symbol("##5#6"))}, getfield(Main, Symbol("##5#6"))(), A)::Base.Generator{Array{Int64,1},getfield(Main, Symbol("##5#6"))}                    │╻╷ Type
     │   %2 = invoke Base._collect(_3::Array{Int64,1}, %1::Base.Generator{Array{Int64,1},getfield(Main, Symbol("##5#6"))}, $(QuoteNode(Base.EltypeUnknown()))::Base.EltypeUnknown, $(QuoteNode(Base.HasShape{1}()))::Base.HasShape{1})::Array{Float64,1}
     └──      return %2   

oh nevermind, I guess the code_warntype basically says how it’s done.

Yes, but

BTW, with union splitting, I wonder if this is still needed. map & friends could just return Any[] for empty collections.