Incorrect diverging implicit expansion with a macro

63 views
Skip to first unread message

Haoyi Li

unread,
Jul 7, 2015, 3:40:38 AM7/7/15
to scala-internals
I posted about this on the gitter channel, but now I think I have a minimal repro, so here it is again

class TC[T]
case class C(nodes: List[C])
import language.experimental.macros
import reflect.macros.blackbox.Context
def impl[T <: C: c.WeakTypeTag](c: Context): c.Expr[TC[T]] = {
  import c.universe._
  def proposal = q"""{
    implicit def m: TC[C] = ???
    implicitly[TC[List[C]]]
    ???
  }"""
  println("typechecked: " + c.typeCheck(proposal, silent = true, withMacrosDisabled = true))
  c.Expr[TC[T]](proposal)
}

implicit def m[T <: C]: TC[T] = macro impl[T]
implicit def listTC[T: TC]: TC[List[T]] = new TC[List[T]]

implicitly[TC[List[C]]]
typechecked: <empty>
<console>:61: error: diverging implicit expansion for type TC[List[C]]
starting with method listTC
         implicitly[TC[List[C]]]

The basic issue is that this should not be a diverging implicit expansion. Although I am trying to infer TC[List[C]] twice in the same macro call-stack, it isn't going to diverge, because in the inner inference I have additional variables in scope that in fact completely shadows the outer implicit that would cause this to diverge. 

Thus it's actually perfectly valid to infer the implicit for the same type twice, since the inner implicit will due to macro expansion resolve to a different implicit from the outer one. Note that if you swap the two Lists for two Options or two Vectors, the problem remains, but if you have one List and one Vector (or some other pair of different types) it works.

This ultimately leads to issues like https://github.com/lihaoyi/upickle/issues/30

Bug? Feature? Anyone have any idea? ^_^

Jason Zaugg

unread,
Jul 7, 2015, 4:51:45 AM7/7/15
to scala-i...@googlegroups.com

I believe think the checking is inline with the spec for divergence checking.

However, you can replace blackbox.Context with whitebox.Context and the compiler will wash its hands of preventing divergence, and it is up to the implicit macro
author: https://gist.github.com/retronym/8501b1b3b113f4386cda

-jason

Haoyi Li

unread,
Jul 8, 2015, 11:05:49 AM7/8/15
to scala-internals
Ok cool, I'll try the whitebox approach. Thanks!

--
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.

Reply all
Reply to author
Forward
0 new messages