Consider the following code: Why is S.|.NotOrNot.OUT
not equal to S.Not
?
sealed trait S
object S {
trait Not extends S
trait A extends S
trait B extends S
trait C extends S
trait |[X <: S, Y <: S] { type OUT <: S }
trait LowerPriorityImplicits {
// implicit def XorNot[X <: S] = |[X, Not, X]
// implicit def NotOrX[X <: S] = |[Not, X, X]
}
object | extends LowerPriorityImplicits {
def apply[X <: S, Y <: S, Z <: S]: X | Y = new |[X, Y] { type OUT = Z }
// implicit def XorX[X <: S] = |[X, X, X]
implicit lazy val NotOrNot = |[Not, Not, Not]
}
}
import S._
def foo[X <: S, Y <: S](implicit ev: X | Y): ev.OUT = null.asInstanceOf[ev.OUT]
val bar = foo[Not, Not]
val baz: Not = foo[Not, Not] // found: S.|.NotOrNot.OUT required: S.Not
EDIT :
Or a condensed example:
trait T { type Out }
object T {
def apply[X]: T = new T { type Out = X }
}
val t = T[Int]
val i: t.Out = 5 // found: Int(5) required: t.Out
But this runs fine:
trait T[O] { type Out = O }
object T {
def apply[X]: T[X] = new T[X] {}
}
val t = T[Int]
val i: t.Out = 5
Your
apply
method says the return type isT
, that is type memberOut
is unspecified.The following specifies the type completely: