I was recently surprised when invocations of Scala's implicitly
was returning null during runtime. I had thought that was unlikely, given that the code shouldn't compile if no implicit instance was available in implicit scope. When is implicitly allowed to return null? Is this a compiler limitation, or is this expected behavior?
Here's some context, if it helps. I'm using shapeless to derive typeclass instances for persisting arbitrary nested case classes. I thought it would be helpful to use implicitly in the nested case classes to check if a typeclass instance could be derived, as it can be unclear where to start looking if the nested case class is large.
So, for example, if I was trying to persist:
case class Foo(bar: Bar, baz: Baz)
and the compiler couldn't derive an instance for my formatter MyFormatter[Foo]
, I started doing something like the following:
case class Bar(i: Int, q: Qux)
object Bar {
implicit val formatter = implicitly[MyFormatter[Bar]]
}
expecting the compiler to tell me that it couldn't find an implicit instance of MyFormatter[Bar]
.
Instead, this was a terrible idea, and my code compiled (when it shouldn't have, as no typeclass instance for Qux could be derived) and Bar.formatter
was null at runtime.
Your implicit definition is recursive.
scala> class C ; object C { implicit val cs: List[C] = implicitly[List[C]] }
defined class C
defined object C
scala> C.cs
res0: List[C] = null
Not only is cs in scope, but object C is in implicit scope for List[C].
Also, it's preferred to specify the type of implicits; sometimes it is necessary for inference to work; and someday it will be required.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With