Consider the following function that, given a tuple `t`

, computes partial products of the elements specified by a second tuple `parts`

as follows

```
function partialprods(t::NTuple{N,Int}, parts::NTuple{M,Int}) where {N,M}
all(0 ≤ i ≤ length(t) for i ∈ parts) || error("Dimension out of range.")
issorted(parts) || error("`parts` must be sorted in ascending order")
ntuple(i -> prod(t[parts[i]+1 : parts[i+1]]), Val(M-1))
end
julia> partialprods((1,2,3,4), (0,2,4))
(2, 12)
```

That is, adjacent elements of `parts`

specify ranges over which to compute the product, and `partialprods`

outputs a tuple containing them.

I observed the following interesting behavior where `partialprods`

is only sometimes type stable (in Julia 1.6.0)

```
julia> wrapper1() = partialprods((1,2,3,4), (0,2,4))
wrapper1 (generic function with 1 method)
julia> wrapper1()
(2, 12)
julia> @code_warntype wrapper1()
Variables
#self#::Core.Const(wrapper1)
Body::Tuple{Int64, Int64}
1 ─ %1 = Core.tuple(1, 2, 3, 4)::Core.Const((1, 2, 3, 4))
│ %2 = Core.tuple(0, 2, 4)::Core.Const((0, 2, 4))
│ %3 = Main.partialprods(%1, %2)::Core.Const((2, 12))
└── return %3
julia> wrapper2() = partialprods((1,2,3,4), (1,3,4))
wrapper2 (generic function with 1 method)
julia> wrapper2()
(6, 4)
julia> @code_warntype wrapper2()
Variables
#self#::Core.Const(wrapper2)
Body::Tuple{Any, Any}
1 ─ %1 = Core.tuple(1, 2, 3, 4)::Core.Const((1, 2, 3, 4))
│ %2 = Core.tuple(1, 3, 4)::Core.Const((1, 3, 4))
│ %3 = Main.partialprods(%1, %2)::Tuple{Any, Any}
└── return %3
```

I would be grateful to anyone who could explain to me what I’ve done that introduces the type instability here. It seems the output type of `partialprods`

should be inferrable from the length of `parts`

, but it is not (always). Note that the first case seems special in that I could not identify another that gave type stable behavior.