-
Notifications
You must be signed in to change notification settings - Fork 21
Description
I just noticed that I broke a library of mine by overriding a trait method in a sub-trait that refines a return type. After introducing this override, implicit resolution is suddenly broken.
The scenario is a bit involved, so please excuse the length of the example.
{code:title=example.scala}
trait Serializer[-Tx, A]
trait Source[-Tx, A] {
def apply()(implicit tx: Tx): A
}
trait Txn[S <: Sys[S]] {
def newHandle[A](value: A)(implicit serializer: Serializer[S#Tx, A]): Source[S#Tx, A]
}
trait Sys[S <: Sys[S]] {
type Tx <: Txn[S]
}
object Foo {
implicit def serializer[S <: Sys[S]]: Serializer[S#Tx, Foo[S]] = ???
}
trait Foo[S <: Sys[S]]
// generic -- works
trait Test1[S <: Sys[S]] {
def test(foo: Foo[S])(implicit tx: S#Tx): Unit = tx.newHandle(foo)
}
// ----
// we can use a refined transaction
trait Txn1[S <: Sys1[S]] extends Txn[S] {
def bar: Unit
}
// refined system
trait Sys1[S <: Sys1[S]] extends Sys[S] {
type Tx = Txn1[S]
}
// example system
trait Sys1In extends Sys1[Sys1In]
// specific -- works
trait Test2 {
type S = Sys1In
def test(foo: Foo[S])(implicit tx: S#Tx): Unit = tx.newHandle(foo)
}
// ----
// introduce a refined result type
trait Source2[-Tx, A] extends Source[Tx, A] {
def baz: Unit
}
// and a refined transaction that uses that result type
trait Txn2[S <: Sys2[S]] extends Txn[S] {
override def newHandle[A](value: A)(implicit serializer: Serializer[S#Tx, A]): Source2[S#Tx, A]
}
// refined system
trait Sys2[S <: Sys2[S]] extends Sys[S] {
type Tx = Txn2[S]
}
// example system
trait Sys2In extends Sys2[Sys2In]
// specific -- FAILS
trait Test3 {
type S = Sys2In
// could not find implicit value for parameter serializer
def test(foo: Foo[S])(implicit tx: S#Tx): Unit = tx.newHandle(foo)
}
{code}