Suppose the following
struct A{T} v::Vector{T} end
Base.convert(::Type{A{T}}, a::A{S}) where {T,S} = A(convert(Vector{T}, a.v))
Base.promote_rule(::Type{A{T}}, ::Type{A{S}}) where {T,S} = A{promote_type(T,S)}
function *(a::A{T}, b::A{S}) where {T,S}
a,b = promote(a,b)
c = typeof(a)(zero(a.v))
for k in eachindex(a.v)
my_product!(c, a, b, k)
end
return c
end
where my_product!
is some customized inlined operation which updates c.v[k]
.
Let a::A{BigFloat}
and b::A{Float64}
. Looking at @code_warntype *(a, b)
shows that the type of b in red as the union of A{Float64}
and A{BigFloat}
but the type of a
is correctly inferred as A{BigFloat}
.
What is the reason for this? I was expecting the compiler to either not know for both or know for both…
Is it critical for performance (assuming my_product!
is type stable of course)? I do see a large time differences by using BenchmarkTools, but it is not clear if it only due to the promote
step in the definition of *
… Is there a macro that can clarify this?