Adding a type parameter annotation symbol that preserves the original bound

myT2_1 describes 4 types (2x2), so that might just go past union-splitting’s limit. I’ll check with a single type parameter, 2 possible types:

julia> struct A{T<:Union{Int64, Float64}} a::T end

julia> struct B b::A end # abstract annotation usually unstable

julia> geta(x::B) = x.b.a
geta (generic function with 1 method)

julia> @code_warntype geta(B(A(1)))
MethodInstance for geta(::B)
  from geta(x::B) @ Main REPL[14]:1
Arguments
  #self#::Core.Const(Main.geta)
  x::B
Body::Union{Float64, Int64}
1 ─ %1 = Base.getproperty(x, :b)::A
│   %2 = Base.getproperty(%1, :a)::Union{Float64, Int64}
└──      return %2

I had to do that little indirection in a field of another struct for the compiler to not specialize over the actual instance’s concrete type, and it does work (a small typo really misled me there). But abstract annotations of fields are intended for limiting compilation, not optimizing type inference or performance. Unless there is a semantic reason for it, I wouldn’t make such a tight constraint at definition, there are plenty of better ways to optimize struct A{T} a::T end.