Annotation in constructor parameter unexpectedly ending up in generated field


#1

Hello all,

According to scala.annotation.meta documentation:

By default, annotations on (val-, var- or plain) constructor parameters end up on the parameter, not on any other entity. Annotations on fields by default only end up on the field.

However if I defined a class like:

class Foo(@Deprecated value: String) {
   override def toString = s"Foo(value=$value)"
}

Then classOf[Foo].getDeclaredField("value").getDeclaredAnnotations returns Array(@java.lang.Deprecated()) while I would expect value field to have no annotation at all.

Is it expected or am I missing anything ?

I’m using scala 2.12.6.

Full example using Scala REPL:

Welcome to Scala 2.12.6 (OpenJDK 64-Bit Server VM, Java 1.8.0_181).
Type in expressions for evaluation. Or try :help.

scala> class Foo(@Deprecated value: String) { override def toString = s"Foo(value=$value)" }
defined class Foo

scala> classOf[Foo].getDeclaredField("value").getDeclaredAnnotations
res0: Array[java.lang.annotation.Annotation] = Array(@java.lang.Deprecated())

scala> import scala.annotation.meta._
import scala.annotation.meta._

scala> class Foo2(@(Deprecated @param) value: String) { override def toString = s"Foo2(value=$value)" }
defined class Foo2

scala> classOf[Foo2].getDeclaredField("value").getDeclaredAnnotations
res1: Array[java.lang.annotation.Annotation] = Array(@java.lang.Deprecated())

Thanks in advance.
Regards


#2

This seems to be a bug indeed. Can you report it at https://github.com/scala/bug/issues?

$> scala -Xprint:cleanup
scala> class Foo(@Deprecated value: String) { override def toString = s"Foo(value=$value)" }
[[syntax trees at end of                   cleanup]] // <console>
...
  class iw$Foo extends Object {
    @Deprecated <paramaccessor> private[this] val value: String = _;
    override def toString(): String = "Foo(value=".+(iw$Foo.this.value).+(")");
    def <init>(@Deprecated value: String): $line3.iw$Foo = {
      iw$Foo.this.value = value;
      iw$Foo.super.<init>();
      ()
    }
  }

The annotation should not be on the field.


#3

Bug reported: https://github.com/scala/bug/issues/11227

Thanks!