I am working on a library where I cannot avoid heterogeneous collections, and I want type-stable code.

I’m trying to improve my understanding of how the compiler behaves in those cases (and in general).

There are already different discussions here related to this topic:

- Type stable accumulator over heterogeneous collection
- Type instability with Union or heterogenous array/tuple
- How is the type of a heterogeneous vector determined when splatting and doing list comprehension?

But they do not fully address my doubts.

My question is associated with the following MWE, divided into two parts.

```
# First part
abstract type BaseType{T} end
getvalue(::BaseType, t) = error("Not implemented")
Base.eltype(::Type{<:BaseType{T}}) where T = T
veltype(::AbstractVector{<:BaseType{T}}) where T = T
struct A{T} <: BaseType{T}
x::T
end
A(x::T) where T = A{T}(x)
getvalue(s::A, t) = s.x + cos(t)
struct B{T} <: BaseType{T}
x::T
end
B(x::T) where T = B{T}(x)
getvalue(s::B, t) = s.x + sin(t)
function loop(v, t)
val = zero(veltype(v))
for vi in v
val += getvalue(vi, t)
end
return val
end
N = 10
v = [i % 2 == 0 ? A(1.0) : B(1.0) for i in 1:N];
t = 1.0
loop(v, t);
@btime loop($v, $t);
# Second part
struct C{T, N} <: BaseType{T}
x::T
end
C(x::T, n) where T = C{T, n}(x)
getvalue(s::C{T, N}, t) where {T, N} = s.x + t
loop(v, 0.0);
@btime loop($v, $t);
```

I believe the **first** part is a *fine* implementation that exploits function barriers, although I’m not sure if can be improved further. My understanding is that within the `loop`

function the `getvalue`

return type is statically dispatched, which is also what I got from `@code_warntype`

(e.g. in this case `Body::Float64`

).

Now adding the **second** part messes up the type stability completely, the `Body`

now is `Any`

and the whole program allocates, although `C`

is not used at all here, and `veltype(v)`

returns the correct type (e.g. `Float64`

).

Can someone help with this?