Unexpected result when promoting Diagonal

When promoting Diagonals with different element types, I’m encountering unexpected behavior:

using LinearAlgebra
diagInt = Diagonal([1])
diagFloat = Diagonal([1.0])
promote_type(typeof(diagInt),typeof(diagFloat)) #returns Diagonal

Instead of Diagonal, I expected Diagonal{Float64, Vector{Float64}}. The promotion should be handled by this promote_rule in the source code, but it seems that it is never called. In fact, if I copy and paste the method into the REPL, the promotion works as expected:

function Base.promote_rule(A::Type{<:Diagonal{<:Any,V}}, B::Type{<:Diagonal{<:Any,W}}) where {V,W}
    X = promote_type(V, W)
    T = eltype(X)
    isconcretetype(T) && return Diagonal{T,X}
    return typejoin(A, B)
end
promote_type(typeof(diagInt),typeof(diagFloat)) #now returns Diagonal{Float64, Vector{Float64}}

Why would overwriting the method with itself change the result?

Hmmm. I do get Diagonal{Float64, Vector{Float64}} on Julia 1.8, but on 1.7 and below it’s Diagonal as you noted.

The only difference afaict is that @_inline_meta in the older versions is replaced by @inline in Julia 1.8, within promote_types body.

Thanks for checking. The answer is indeed that the method is not present on versions earlier than 1.8, and I’m using 1.7.3. It was added in this commit.

1 Like