I have a function `f`

that is potentially type-unstable. I also have a function `g`

that in the end is type-stable, but inside it calls `f`

.

Here is an (artificial) example, implemented in different ways:

```
f1(t::Tuple, i::Int) = t[i]
g1(thetupl::Tuple, ::Val{n}) where {n} = ntuple(i -> f1(thetupl, i), Val(n))
f2(t::Tuple, ::Val{i}) where {i} = t[i]
g2(thetupl::Tuple, ::Val{n}) where {n} = ntuple(i -> f2(thetupl, Val(i)), Val(n))
f3(t::Tuple, ::Val{i}) where {i} = t[i]
f3(t::Tuple, i::Int) = t[i]
g3(thetupl::Tuple, ::Val{n}) where {n} = ntuple(i -> f3(thetupl, i), Val(n))
g4(thetupl::Tuple, ::Val{n}) where {n} = ntuple(i -> f3(thetupl, Val(i)), Val(n))
f5(t::Tuple, i::Int) = f2(t::Tuple, Val(i))
g5(thetupl::Tuple, ::Val{n}) where {n} = ntuple(i -> f5(thetupl, i), Val(n))
```

All the versions of `g`

are type-stable (in theory). However `f1`

, `f3`

, `f5`

are potentially type-unstable because their output types can depend on the *value* of `i`

, when the tuple `t`

has items of heterogeneous types.

To experiment, I created an heterogeneous tuple:

```
julia> thetupl = ntuple(i -> rand((rand(1:10), rand("da;glaergerf"), "afdsa", rand(Bool), randn())), 20)
("afdsa", false, false, "afdsa", "afdsa", true, 9, false, 4, false, 'l', 'l', 'e', false, 0.21198045684894534, -0.9550998919808197, 'f', false, "afdsa", "afdsa")
```

Then I inspected the type-stability of the different versions of `g`

as inferred by Julia, using `@inferred g1(thetupl, Val(5))`

, and so on for the other variations of `g`

. Turns out that `g1`

, `g3`

are seen as type-stable by Julia, while `g2`

, `g4`

, `g5`

are not! I was surprised by this, and would like to understand why.

I actually have some slightly more complicated code with a related issue, so I am trying to understand what is the best way to deal with these “spurious” type instabilities inside type-stable functions.

In case this depends on compiler internals that might change with version, I am using Julia 1.3.1 here.