Thatβs because it does not now how many iterators it will be taking the product of if you input them via a vector. If possible, use a tuple of iterators as input argument
julia> f(m)=collect(Iterators.product(m...))
f (generic function with 1 method)
julia> @code_warntype f([1:2,3:5])
Body::Any
1 1 β %1 = (Core._apply)(Base.Iterators.product, m)::Any β
β %2 = (Main.collect)(%1)::Any β
βββ return %2
julia> @code_warntype f((1:2,3:5))
Body::Array{Tuple{Int64,Int64},2}
1 1 ββ %1 = (getfield)(m, 1)::UnitRange{Int64}
β %2 = (getfield)(m, 2)::UnitRange{Int64}
β %3 = (Core.tuple)(%1, %2)::Tuple{UnitRange{Int64},UnitRange{Int64}}
β %4 = %new(Base.Iterators.ProductIterator{Tuple{UnitRange{Int64},UnitRange{Int64}}}, %3)::Base.Iterators.ProductIterator{Tuple{UnitRange{Int64},UnitRange{Int64}}}
β (Base.ifelse)(true, 1, 0) Colon
β %6 = (Base.getfield)(%1, :stop)::Int64 _similar_for
β %7 = (Base.getfield)(%1, :start)::Int64 axes
β %8 = (Base.Checked.checked_ssub_int)(%6, %7)::Tuple{Int64,Bool}
β %9 = (Base.getfield)(%8, 1, true)::Int64 _prod_axes1
β %10 = (Base.getfield)(%8, 2, true)::Bool axes
ββββ goto #3 if not %10 βββββββββ» size
2 ββ invoke Base.Checked.throw_overflowerr_binaryop(:-::Symbol, %6::Int64, %7::Int64)
ββββ $(Expr(:unreachable))ββββββββββ checked_sub
3 ββ goto #4 βββββββββββ
4 ββ %15 = (Base.Checked.checked_sadd_int)(%9, 1)::Tuple{Int64,Bool}erflow
β %16 = (Base.getfield)(%15, 1, true)::Int64 indexed_iterate
β %17 = (Base.getfield)(%15, 2, true)::Bool getindex
ββββ goto #6 if not %17 βββββββββββ» checked_add
5 ββ invoke Base.Checked.throw_overflowerr_binaryop(:+::Symbol, %9::Int64, 1::Int64)
ββββ $(Expr(:unreachable))ββββββββββ
6 ββ goto #7 βββββββββββ
7 ββ goto #8 ββββββββββ
8 ββ goto #9 βββββββββ
9 ββ %24 = (Base.slt_int)(%16, 0)::Boolββ»β·β·β· Type
β %25 = (Base.ifelse)(%24, 0, %16)::Int64 Type
ββββ goto #10 ββββββββ
10 β goto #11 βββββββ
11 β %28 = (Base.getfield)(%2, :stop)::Int64 _prod_axes1
β %29 = (Base.getfield)(%2, :start)::Int64 axes
β %30 = (Base.Checked.checked_ssub_int)(%28, %29)::Tuple{Int64,Bool}
β %31 = (Base.getfield)(%30, 1, true)::Int64 length
β %32 = (Base.getfield)(%30, 2, true)::Bool checked_sub
ββββ goto #13 if not %32 ββββββββββββ» checked_sub
12 β invoke Base.Checked.throw_overflowerr_binaryop(:-::Symbol, %28::Int64, %29::Int64)
ββββ $(Expr(:unreachable))βββββββββββ
13 β goto #14 ββββββββββββ
14 β %37 = (Base.Checked.checked_sadd_int)(%31, 1)::Tuple{Int64,Bool}erflow
β %38 = (Base.getfield)(%37, 1, true)::Int64 indexed_iterate
β %39 = (Base.getfield)(%37, 2, true)::Bool getindex
ββββ goto #16 if not %39 ββββββββββββ» checked_add
15 β invoke Base.Checked.throw_overflowerr_binaryop(:+::Symbol, %31::Int64, 1::Int64)
ββββ $(Expr(:unreachable))βββββββββββ
16 β goto #17 ββββββββββββ
17 β goto #18 βββββββββββ
18 β goto #19 ββββββββββ
19 β %46 = (Base.slt_int)(%38, 0)::Boolβββ»β·β·β· Type
β %47 = (Base.ifelse)(%46, 0, %38)::Int64 Type
ββββ goto #20 βββββββββ
20 β goto #21 ββββββββ
21 β goto #22 βββββββ
22 β goto #23 ββββββ
23 β goto #24 βββββ
24 β %53 = $(Expr(:foreigncall, :(:jl_alloc_array_2d), Array{Tuple{Int64,Int64},2}, svec(Any, Int64, Int64), :(:ccall), 3, Array{Tuple{Int64,Int64},2}, :(%25), :(%47), :(%47), :(%25)))::Array{Tuple{Int64,Int64},2}
ββββ goto #25 ββββ
25 β %55 = invoke Base.copyto!(%53::Array{Tuple{Int64,Int64},2}, %4::Base.Iterators.ProductIterator{Tuple{UnitRange{Int64},UnitRange{Int64}}})::Array{Tuple{Int64,Int64},2}
ββββ goto #26 βββ
26 β goto #27 ββ
27 β return %55 β