Why calling c.eval on annotation with default parameters sometimes fails and sometimes doesn't?

I have the following code for evaluating annotations:

    def evalAnnotation[A : c.WeakTypeTag](symbol: c.Symbol): Option[A] = {
      for (a <- symbol.annotations.find(_.tree.tpe.typeSymbol == weakTypeOf[A].typeSymbol))
        yield c.eval(c.Expr[A](c.untypecheck(a.tree.duplicate)))
    }

And in another package of the same module there are the following annotations:

package object annotations {
  case class udt(name: String = "") extends StaticAnnotation
  case class table(name: String = "") extends StaticAnnotation
}

At the client code module, I place these annotations on classes.
Now, a funny thing is that if I put both of these annotations at some class:

@udt @table case class Foo(....)

And then I try to evaluate them in the macro one after another like this:

    val udtAnnotation = evalAnnotation[annotations.udt](fooType.typeSymbol)
    println(udtAnnotation)
    val tableAnnotation = evalAnnotation[annotations.table](fooType.typeSymbol)
    println(tableAnnotation)

It miserably fails on the second annotation evaluation. When I had only one annotation in the project, it worked fine every single time.

The error I get is this:

Some(udt(null))
exception when typing com.xxxx.annotations.`package`.table.<init>$default$1()/class scala.reflect.internal.Trees$Apply
=> String @annotation.unchecked.uncheckedVariance does not take parameters in file <no file>
scala.reflect.internal.Types$TypeError: => String @annotation.unchecked.uncheckedVariance does not take parameters
	at scala.tools.nsc.typechecker.Contexts$ThrowingReporter.handleError(Contexts.scala:1402)
	at scala.tools.nsc.typechecker.Contexts$ContextReporter.issue(Contexts.scala:1254)
	at scala.tools.nsc.typechecker.Contexts$Context.issue(Contexts.scala:573)
	at scala.tools.nsc.typechecker.Typers$Typer.scala$tools$nsc$typechecker$Typers$Typer$$duplErrorTree$1(Typers.scala:3213)
	at scala.tools.nsc.typechecker.Typers$Typer.doTypedApply(Typers.scala:3550)
	at scala.tools.nsc.typechecker.Typers$Typer.normalTypedApply$1(Typers.scala:4580)
	at scala.tools.nsc.typechecker.Typers$Typer.typedApply$1(Typers.scala:4608)
	at scala.tools.nsc.typechecker.Typers$Typer.typedInAnyMode$1(Typers.scala:5370)
	at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5387)
	at scala.tools.nsc.transform.Erasure$Eraser.typed1(Erasure.scala:712)
     ....
exception when typing new com.xxxx.annotations.package.table(com.xxxx.annotations.`package`.table.<init>$default$1())
exception when typing def wrapper(): Object = new com.xxxx.annotations.package.table(com.xxxx.annotations.`package`.table.<init>$default$1())
exception when typing object __wrapper$3$4bd49eefedc34622810a80749b07572f extends Object {
  def <init>(): __wrapper$3$4bd49eefedc34622810a80749b07572f.__wrapper$3$4bd49eefedc34622810a80749b07572f.type = {
    __wrapper$3$4bd49eefedc34622810a80749b07572f.super.<init>();
    ()
  };
  def wrapper(): Object = new com.xxxx.annotations.package.table(com.xxxx.annotations.`package`.table.<init>$default$1())
}
exception when typing package __wrapper$3$4bd49eefedc34622810a80749b07572f {
  object __wrapper$3$4bd49eefedc34622810a80749b07572f extends Object {
    def <init>(): __wrapper$3$4bd49eefedc34622810a80749b07572f.__wrapper$3$4bd49eefedc34622810a80749b07572f.type = {
      __wrapper$3$4bd49eefedc34622810a80749b07572f.super.<init>();
      ()
    };
    def wrapper(): Object = new com.xxxx.annotations.package.table(com.xxxx.annotations.`package`.table.<init>$default$1())
  }
}

Is it a bug? Why is one failing, when another identical one evaluates just fine?
If I specify the value of name in these annotations, they evaluate ok. Therefore, there must be something wrong with default value handling.

And finally - how to make that reliable?
This is Scala version 2.11.12.

I think I found the culprit. Moving the annotations from the package object to the real package solved the problem. I believe this must be a Scala bug.

1 Like