== for custom type and promote_rule

From the docs for ==:

New numeric types should implement this function for two arguments of the new type, and handle comparison to other types via promotion rules where possible.

So I tried this:

struct A
  x::Float64
end

struct B
  x::Int
end

Base.convert(::Type{A}, s::B) = A(float(B.x))
Base.:(==)(x::A, y::A) = x.x == y.x
Base.:(==)(x::B, y::B) = x.x == y.x
Base.promote_rule(::Type{A}, ::Type{B}) = A

But A(1) == B(1) returns false, because it is falling back to ===.

From the documentation I was expecting that the promotion would occur here and then A(1) == B(1) would be true.

Did I misread the docs here? What’s the proper way to handle this? Do I have to define

Base.:(==)(x::A, y::B) = x.x == y.x
Base.:(==)(x::B, y::A) = x.x == y.x

as well?

There is no implicit promotion for general structs, you can define e.g.

==(a::A, b::B) = ==(promote(A, B)...)
==(a::B, b::A) = A == B

But typically these would share some common super type (let’s say C) and you would define

==(a::C, b::C) = ==(promote(A, B)...)
2 Likes

I see, thanks.

If there is no super type I guess I can do

==(a::Union{A,B}, b::Union{A,B}) = ==(promote(a,b)...)