Resolving UnionAlls with a single concrete instance in struct declarations

This is something I’ve encountered far too often, and it’s one of my biggest gripes with Julia. @Tamas_Papp explained it best:

I’ve encountered issues with this in the past with CliffordNumbers.jl: subtypes of AbstractCliffordNumber{Q,T} need an extra type parameter (for instance, KVector{K,Q,T,L}) where L is the length of the backing NTuple{L,T}. For this type, L = binomial(dimension(Q), K), so it’s not particularly simple arithmetic.

There’s good reason not to allow arbitrary computation in the type system, but this either becomes a pitfall for new Julia programmers, or an annoyance for those who have to leak type parameters when building a struct out of types like these.

Can there be a mechanism for the Julia compiler to resolve almost concrete types in struct declarations like SMatrix{N,N,T}, which only have a single concrete instance, to avoid the type instability and performance hit? Perhaps some sort of function, like

Base.resolve_to_concrete_type(::Type{SMatrix{M,N,T}}) = SMatrix{M,N,T,M*N}

function Base.resolve_to_concrete_type(::Type{KVector{K,Q,T}}) where {K,Q,T}
    return KVector{K,Q,T,binomial(dimension(Q), K)}
end

which a user can opt into to cover cases like this?

Assuming you meant one instantiable concrete subtype, that’s entirely enforced by the implementation flagging or fixing an incomplete or inappropriate type like SMatrix{2,2,Int,3}, not the language itself. If we circumvent those methods with type piracy or the below hack, we can actually instantiate those inappropriate types:

julia> x = eval(Expr(:new, SMatrix{2,2,Int,6}, Tuple(1:6)))
2×2 SMatrix{2, 2, Int64, 6} with indices SOneTo(2)×SOneTo(2):
 1  3
 2  4

julia> eachindex(x), x[5], x[6]
(SOneTo(4), 5, 6)

In the general case, new constructor methods can make more reasonable exceptions to obvious computed types and thus make omitted type parameters not redundant after all. This essentially amounts to “arbitrary computation in the type system,” brittle and dangerous for a dynamic language.