I'm having a compiler type mismatch error that I do not understand.
Given the following definition of an Elem
and a factory (Companion
):
object Elem {
trait Companion[E[~] <: Elem[~]] {
def apply[S](peer: E[S]#Peer): E[S] // wrap a peer in its elem
}
}
trait Elem[S] {
type Peer
}
And given for example an Obj
with attributes and a peer type Expr
:
trait Expr[S, A]
trait Obj[S] {
// query an attribute by key
def attr[E[~] <: Elem[~]](key: String)
(implicit c: Elem.Companion[E]): Option[E[S]#Peer]
}
I should be able to do the following:
// process elements with peer `Expr[~, A]`
trait Impl[S, A, E[~] <: Elem[~] { type Peer = Expr[~, A] }] {
implicit def companion: Elem.Companion[E]
def test(obj: Obj[S]): Unit =
obj.attr[E]("foo").fold(()) { ex =>
val newElem = companion[S](ex)
}
}
This last bit fails with the brilliant error message:
<console>:62: error: type mismatch;
found : E[S]#Peer
(which expands to) Expr[S,A]
required: E[S]#Peer
(which expands to) Expr[S,A]
val newElem = companion[S](ex)
^
I reduced your example to the following:
trait Elem {
type Peer
}
trait Impl[E[~] <: Elem {type Peer = ~}] {
def foo[R](peer: E[R]#Peer)
foo[Int](??? : E[Int]#Peer)
}
where scalac gives
Error:(12, 18) type mismatch;
found : this.scala.Peer
(which expands to) Int
required: this.Peer(in method foo)
(which expands to) R
foo[Int](??? : E[Int]#Peer)
^^
I'm not sure, but this looks like a Scala bug, since R
isn't even in scope at the site of the error -- it seems to have leaked out. Scala seems to be failing to perform the substitution R = Int
inside the refinement, allowing the parameter R
to remain.