I have this code:
trait Context {
implicit val e: Encoder
trait Encoder {
def write(): Unit = {
println("Test")
}
}
}
trait AsyncEncoders {
this: Context =>
class AsyncEncoder extends Encoder {
}
implicit val e = new AsyncEncoder()
}
class ConcreteContext extends Context with AsyncEncoders {
}
When I use it like this (case 1):
object Main extends App {
implicit val c = new ConcreteContext()
import c._
implicitly[Encoder].write()
}
then it compiles and prints Test
.
But when I try to call the same code inside singleton object (case 2):
object TestObject {
def apply()(implicit c: ConcreteContext): Unit = {
import c._
implicitly[Encoder].write()
}
}
object Main extends App {
implicit val c = new ConcreteContext()
TestObject()
}
compilation fails with:
path/to/Main.scala:29: could not find implicit value for parameter e: c.Encoder implicitly[c.Encoder].write()
If I change (case 3):
implicit val e = new AsyncEncoder()
to
implicit val e: Encoder = new AsyncEncoder()
then it compiles and runs as expected.
But for some reason this is not acceptable for me.
Why does compilation fail in the above case?
As it said in comments there is no issue in Scala 2.12.0.
For Scala 2.11.8 I used the following workaround assuming that Encoder
will have only one method:
trait Context {
implicit val e: Encoder
type BaseEncoder = () => Unit
type Encoder <: BaseEncoder
}
trait AsyncEncoders {
this: Context =>
type Encoder = AsyncEncoder
class AsyncEncoder extends BaseEncoder {
override def apply(): Unit = {
println("Test")
}
}
implicit val e = new AsyncEncoder()
}
class ConcreteContext extends Context with AsyncEncoders {
}
object TestObject {
def apply()(implicit c: ConcreteContext): Unit = {
import c._
implicitly[Encoder].apply()
}
}
object Main extends App {
implicit val c = new ConcreteContext()
TestObject()
}