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?