Interesting point. Thank you for the answer.
I tested it with the struct you described and it gives:
Body::AbstractVector{var"#s827"} where var"#s827"
1 ─ %1 = Core.apply_type(Main.Array, Main.Float32, 3)::Core.Const(Array{Float32, 3})
│ %2 = Core.apply_type(Main.Vector, %1)::Core.Const(Vector{Array{Float32, 3}})
│ %3 = Core.apply_type(Main.Array, Main.Float32, 2)::Core.Const(Matrix{Float32})
│ %4 = Core.apply_type(Main.Vector, %3)::Core.Const(Vector{Matrix{Float32}})
│ %5 = Core.apply_type(Main.me, %2, %4)::Core.Const(me{Vector{Array{Float32, 3}}, Vector{Matrix{Float32}}})
│ %6 = Main.randn(Main.Float32, 2, 1, 1)::Array{Float32, 3}
│ %7 = Base.vect(%6)::Vector{Array{Float32, 3}}
│ %8 = Main.randn(Main.Float32, 2, 1)::Matrix{Float32}
│ %9 = Base.vect(%8)::Vector{Matrix{Float32}}
│ (m = (%5)(%7, %9))
│ %11 = Main.foo(m)::AbstractVector{var"#s827"} where var"#s827"
└── return %11
Instead of this:
Body::Vector{Array{Float32, 3}}
1 ─ %1 = Core.apply_type(Main.Array, Main.Float32, 3)::Core.Const(Array{Float32, 3})
│ %2 = Core.apply_type(Main.Vector, %1)::Core.Const(Vector{Array{Float32, 3}})
│ %3 = Core.apply_type(Main.Array, Main.Float32, 2)::Core.Const(Matrix{Float32})
│ %4 = Core.apply_type(Main.Vector, %3)::Core.Const(Vector{Matrix{Float32}})
│ %5 = Core.apply_type(Main.me, %2, %4)::Core.Const(me{Vector{Array{Float32, 3}}, Vector{Matrix{Float32}}})
│ %6 = Main.randn(Main.Float32, 2, 1, 1)::Array{Float32, 3}
│ %7 = Base.vect(%6)::Vector{Array{Float32, 3}}
│ %8 = Main.randn(Main.Float32, 2, 1)::Matrix{Float32}
│ %9 = Base.vect(%8)::Vector{Matrix{Float32}}
│ (m = (%5)(%7, %9))
│ %11 = Main.foo(m)::Vector{Array{Float32, 3}}
└── return %11
So I don’t think the struct has anything to do with the problem.
Btw, I am still looking for the answer why does this replacement of this
double(x::Vector{Array{Float32, 3}}) = 2 .* x with this double(x::Vector{Array{Float32, 3}}) = 2.f0 .* x solves the problem.
By the way thank you for the StaticArrays idea, I never understood what is that and I will look after that too.