struct X {
/* something */ operator<=>(const X&); // member, compares X
};
X x;
struct Y : X { };
Y y;
x == x (obviously) works.
x == y gets us (x <=> y) == 0 which works (conversion on second param)
y == x: We check whether 0 == (x <=> y) works (yes, it does), so we add the
synthesized candidate
op<=>(const X&, const X& implicit_obj_param)
to the candidate set for ==. The total candidate set for y==x is
op<=>(const X& implicit_obj_param, const X&);
op<=>(const X&, const X& implicit_obj_param); // #2
Then, we match y==x against this and we convert y to X (first param of #2).
What bothers me a bit is that the property "implicit object param" (which prevents conversions on that operand) is not explicitly mentioned as being swapped in 16.3.1.2p6.2.