Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When can Scala's implicitly return null?

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.

like image 823
Josh Marcus Avatar asked Feb 06 '23 15:02

Josh Marcus


1 Answers

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.

like image 180
som-snytt Avatar answered Feb 09 '23 04:02

som-snytt