Can we use upper and lower bounds of type parameters for equivalence test?

I have the following code:

  trait TT
  class TT1 extends TT
  class TT2 extends TT
  class TT3 extends TT1

  val tt1 = TT1()
  val tt2 = TT2()
  val tt3 = TT3()

  def callAny[T <: TT](s:T) = ???

  def call1[T <: TT1](s:T) = ???
  call1(tt3)   // avoid this
  //call1(tt2) // Ok won't compile

  def callOnly1[S <: TT1, T >: TT1](s:S with T) = ???
  callOnly1(tt1) // Ok
  callOnly1(tt3) // Should fail

Note that I want the last example to fail.

Can I use a combination of <:and >: to enforce equivalence? If so, how can I do this in Scala3 (dotty)?


The combination of <: with >: will not work, as T >: TT1 means some supertype of TT1, which still will be a supertype of any class extending TT1.

Instead, for type equivalence checks you can use implicits / givens. The standard library defines the given instance =:=[T,U] for every type, where T and U are the same. In Dotty, you’ll use it like this:

def callOnly1[T](t:T)(using T =:= TT1) = t

This will cause a “Cannot prove that TT3 =:= TT1.” compile time error on the line you want to fail see Scastie

1 Like

@crater2150 Thanks. I have seen examples of the equivalence test. However, do you have any example that shows the use of a combination of <: with >:? I am trying to see how one could use this kind of constraint.

EDIT: neglected to mention that this is for Dotty/Scala 3