Catching the exact static type of a parameter

The following code does compile, even though B() and C() are of different types. I believe this is because both are of type A, so that X gets set to A by the compiler when type checking foo(B(), C()).

class A
class B extends A
class C extends B

def foo[X <: A](x: X, y: X): X = x

def bar(): Unit = {
  foo(B(), C())
}

Could I somehow change the definition of foo in such a way that it would force x and y to have exactly the same static type (their most specific static type), while still being generic? In such a way that foo(B(), C()) would result in a type error?

I can think of 2 ways, both are quite cumbersome

Using implicit evidence as captured here: Scastie - An interactive playground for Scala.

Using a second argument list such as

def foo[X <: Y](x: X)(y: X): X = x
2 Likes