implicitly assigned to implicit val evaluates to null

34 views
Skip to first unread message

Rintcius Blok

unread,
Jul 21, 2015, 4:51:44 PM7/21/15
to scala-internals
Hi,

I ran into an issue which I could minimize like below. It looks like a bug to me since I think the last line should not compile (in the same way as the one before)?
Just wanted to confirm before creating a bug report that it is indeed a bug and that it is not already known (although I couldn't find it).

- Rintcius

Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_45).

scala> import scala.language.higherKinds
import scala.language.higherKinds

scala> trait M[F[_]]
defined trait M

scala> case class Foo[A]()
defined class Foo

scala> val f: M[Foo] = implicitly[M[Foo]]  
<console>:14: error: could not find implicit value for parameter e: M[Foo]
       val f: M[Foo] = implicitly[M[Foo]]
                                 ^
scala> implicit val f: M[Foo] = implicitly[M[Foo]]
f: M[Foo] = null

Jon Pretty

unread,
Jul 21, 2015, 5:03:28 PM7/21/15
to scala-internals
Hi Rintcius,

That's not a bug, though in some sense in shouldn't work. In the same way that you're able to write a self-referential val, e.g.

   val foo: Int = 10 + foo

Scala can equally find that value by type, i.e. with implicit search.

The justification, I suppose, is that introducing a new scope, as would be necessary to preclude `f` from implicit consideration, would fix only this one, very specific evaluation order issue, but there are plenty more opportunities to access an unevaluated val which it wouldn't fix. Maybe that's a weak argument.

Incidentally, without the type ascription on `f`, compilation will fail, as desired, though that's hardly a solution...

Cheers,
Jon

--
You received this message because you are subscribed to the Google Groups "scala-internals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-interna...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Jon Pretty | @propensive

Rintcius Blok

unread,
Jul 22, 2015, 4:09:47 AM7/22/15
to scala-internals
Hi Jon,

Thanks, that makes sense. Maybe the core of what I'm still wondering is if there should be any case where 
val <something> = <somethingelse> 
does not compile but 
implicit val <something> = <somethingelse> 
does.

- Rintcius

Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_45).

scala> val i:Int = implicitly[Int]
<console>:10: error: could not find implicit value for parameter e: Int
       val i:Int = implicitly[Int]
                             ^

scala> implicit val j:Int = implicitly[Int]
j: Int = 0


Jon Pretty

unread,
Jul 22, 2015, 5:06:29 AM7/22/15
to scala-internals
Maybe this is cheating, but how about:

case class Foo(foo: () => Foo)
val foo = new Foo(() => foo)
foo.foo().foo().foo() // doesn't return `null`

Basically, I think the logic required to work out whether the val is self-referential is nontrivial at worst, and at best, not done.

Cheers,
Jon

Rintcius Blok

unread,
Jul 22, 2015, 7:04:20 AM7/22/15
to scala-internals


On Wednesday, July 22, 2015 at 11:06:29 AM UTC+2, Jon Pretty wrote:
Maybe this is cheating, but how about:

case class Foo(foo: () => Foo)
val foo = new Foo(() => foo)
foo.foo().foo().foo() // doesn't return `null`

Ok, I think you mean (i.e. with type ascription to make it compile):  val foo:Foo = Foo(() => foo).
That's not an example of what I mentioned though (see below)?


Basically, I think the logic required to work out whether the val is self-referential is nontrivial at worst, and at best, not done.
 
With that part I definitely agree. I was wondering if it is worth it to *circumvent* having to look at self-reference by first checking if val <something> = <somethingelse> compiles.
If it doesn't then implicit val <something> = <somethingelse> would also not compile (with the same message). 

E.g. below the last statement then wouldn't compile with the same messages as the first.

scala> val d:Double = Math.sin(12 * implicitly[Double]) + Math.cos(implicitly[Double] + 10)
<console>:10: error: could not find implicit value for parameter e: Double
       val d:Double = Math.sin(12 * implicitly[Double]) + Math.cos(implicitly[Double] + 10)
                                              ^
<console>:10: error: could not find implicit value for parameter e: Double
       val d:Double = Math.sin(12 * implicitly[Double]) + Math.cos(implicitly[Double] + 10)
                                                                             ^

scala> implicit val d:Double = Math.sin(12 * implicitly[Double]) + Math.cos(implicitly[Double] + 10)
d: Double = -0.8390715290764524

Reply all
Reply to author
Forward
0 new messages