This has nothing to do with implicit resolution but rather type inference.
I really do not understand why do you expect your commented examples to compile, but let me try to explain what is the problem.
val o3: Ordering[X] = Ordering.by(_.t).reverse
So according to the docs
by expects a
A => B and given an
Ordering[B] it provides an
Ordering[A] (so in plain English, it is quite simple, if I know how to order something and I know how to get that something from something else, then I know how to order that something else by something).
Here the compiler has zero information about what is the type of the input of the function, so it can not infer the output of the function so it does not type-check. It works in
o1 because it can use the expected return type of of the whole expression to infer the type of the input; in this case, since there is another call after
by the inference can not use that information.
So you need to help the compiler know what is your input type:
// You do not even need the explicit return type
val o3 = Ordering.by[X, T](_.t).reverse
val o3 = Ordering.by((x: X) => x.t).reverse
The same happens with
You can see them running here.
One may argue that the compile could try harder with the type inference by seeing that
reverse returns the same type… I know Scala 3 will improve its type inference, but I do not know if this would work, flowing types on more complex expressions may be pretty slow and maybe not be that useful.