Type parameters not being passed correctly to macro?

69 views
Skip to first unread message

Haoyi Li

unread,
Jul 5, 2015, 1:53:42 PM7/5/15
to scala-internals
There are two bugs here. Not sure if these are known bugs on file, but a cursory googling didn't find anything. Anyone have any idea if there are workarounds for these?

The first one is a type losing its type parameters when passed into a macro implementation directly from the macro call:

Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_25).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import language.experimental._
import language.experimental._

scala>   import reflect.macros.blackbox.Context
import reflect.macros.blackbox.Context

scala>   def macroImpl[T](c: Context)(implicit e: c.WeakTypeTag[T]): c.Expr[String] = {
     |     import c.universe._
     |     c.Expr[String](q"${e.toString}")
     |   }
macroImpl: [T](c: scala.reflect.macros.blackbox.Context)(implicit e: c.WeakTypeTag[T])c.Expr[String]

scala>   def m = macro macroImpl[Seq[Int]]
warning: there was one deprecation warning; re-run with -deprecation for details
defined term macro m: String

scala> m
res3: String = WeakTypeTag[Seq[A]]

The second one is that for some reason `Nothing` is becoming `T` when passed into an implicit macro

Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_25).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import language.experimental.macros
import language.experimental.macros

scala> import reflect.macros.Context
import reflect.macros.Context

scala> case class S[T](s: String)
defined class S

scala> def impl[T: c.WeakTypeTag](c: Context): c.Expr[S[T]] = {import c.universe._; c.Expr[S[T]](q"S[${weakTypeOf[T]}](${weakTypeOf[T].toString})")}
warning: there was one deprecation warning; re-run with -deprecation for details
impl: [T](c: reflect.macros.Context)(implicit evidence$1: c.WeakTypeTag[T])c.Expr[S[T]]

scala> implicit def m[T]: S[T] = macro impl[T]
defined term macro m: [T]=> S[T]

scala> m[Nothing]
res0: S[Nothing] = S(Nothing)

scala> implicitly[S[Nothing]](m)
res1: S[Nothing] = S(T)

scala> implicitly[S[Nothing]](m[Nothing])
res2: S[Nothing] = S(Nothing)

scala>

Eugene Burmako

unread,
Jul 6, 2015, 9:01:13 AM7/6/15
to <scala-internals@googlegroups.com>
The first one is definitely a bug.

The second one is actually a consequence of a feature. Unlike normal macros (and unlike blackbox implicit macros), whitebox implicit macros try not to force the type inferencer's hand and accept uninferred type parameters as is, without requiring them to be instantiated to default values (e.g. to Nothing). Unfortunately, there's an annoying limitation in the mechanism that implements this, and it leads to the behavior that you've uncovered. More information can be found here: https://github.com/scala/scala/commit/21a8c6c7558a67b642b6827f716b1aba2244c97f#diff-5e93589266ed06aef7393b820978168aR7.

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

Eugene Burmako

unread,
Jul 6, 2015, 9:25:20 AM7/6/15
to <scala-internals@googlegroups.com>
I've taken a look at the first bug, and it looks like the logic that computes values for type tags that get passed to macro impls is thoroughly screwed up [1].

Unfortunately, it looks like only the simplest type parameters are going to work fine (e.g. `def foo[T] = macro impl[T]`), and the rest just doesn't have a chance (e.g. `def foo[T] = macro impl[List[T]]`). Your case falls into the latter category. While the fix for your particular issue is simple [2], it won't address the other problems :(

In retrospective, I would say that the cost of introducing a special language form to bind macro defs and macro impls ended up being unexpectedly huge. There were (and probably still are) countless bugs that hide in the right-hand side of macro defs...

Haoyi Li

unread,
Jul 7, 2015, 12:40:53 AM7/7/15
to scala-internals
Unfortunately, there's an annoying limitation in the mechanism that implements this, and it leads to the behavior that you've uncovered. More information can be found here

Is this a bug or a feature? Would it be worth filing an issue on JIRA?

I've taken a look at the first bug, and it looks like the logic that computes values for type tags that get passed to macro impls is thoroughly screwed up

Does this have a JIRA entry too? =P I'd love to be able to link to somewhere saying "don't blame me, blame scalac..." when I write dumb code like https://github.com/lihaoyi/upickle/blob/configuration/upickle/shared/src/main/scala/upickle/Api.scala#L12-L29

Eugene Burmako

unread,
Jul 7, 2015, 2:58:30 AM7/7/15
to <scala-internals@googlegroups.com>
I think it will be useful to file both to have the definitive point of reference. Thanks!
Reply all
Reply to author
Forward
0 new messages