summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala20
-rw-r--r--src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala131
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Constants.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala10
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala24
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala22
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala4
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala56
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala44
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala25
-rw-r--r--test/files/pos/t1782/Ann.java3
-rw-r--r--test/files/pos/t1782/Days.java3
-rw-r--r--test/files/pos/t1782/Test_1.scala3
15 files changed, 159 insertions, 194 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 9cfdf24ffc..ef2d98a053 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -162,8 +162,8 @@ abstract class GenJVM extends SubComponent {
parents = parents ::: List(definitions.SerializableClass.tpe)
case AnnotationInfo(tp, _, _) if tp.typeSymbol == CloneableAttr =>
parents = parents ::: List(CloneableClass.tpe)
- case AnnotationInfo(tp, value :: _, _) if tp.typeSymbol == SerialVersionUID =>
- serialVUID = Some(value.constant.get.longValue)
+ case AnnotationInfo(tp, Literal(const) :: _, _) if tp.typeSymbol == SerialVersionUID =>
+ serialVUID = Some(const.longValue)
case AnnotationInfo(tp, _, _) if tp.typeSymbol == RemoteAttr =>
parents = parents ::: List(RemoteInterface.tpe)
remoteClass = true
@@ -317,9 +317,10 @@ abstract class GenJVM extends SubComponent {
buf.putShort(0xbaba.toShort)
for (AnnotationInfo(tp, List(exc), _) <- excs.removeDuplicates if tp.typeSymbol == ThrowsAttr) {
+ val Literal(const) = exc
buf.putShort(
cpool.addClass(
- javaName(exc.constant.get.typeValue.typeSymbol)).shortValue)
+ javaName(const.typeValue.typeSymbol)).shortValue)
nattr += 1
}
@@ -337,8 +338,8 @@ abstract class GenJVM extends SubComponent {
annot.args.isEmpty)
private def emitJavaAnnotations(cpool: JConstantPool, buf: ByteBuffer, annotations: List[AnnotationInfo]): Int = {
- def emitArgument(arg: ConstantAnnotationArgument): Unit = arg match {
- case LiteralAnnotationArgument(const) =>
+ def emitArgument(arg: ClassfileAnnotArg): Unit = arg match {
+ case LiteralAnnotArg(const) =>
const.tag match {
case BooleanTag =>
buf.put('Z'.toByte)
@@ -376,12 +377,12 @@ abstract class GenJVM extends SubComponent {
buf.putShort(cpool.addUtf8(const.symbolValue.name.toString).toShort)
}
- case ArrayAnnotationArgument(args) =>
+ case ArrayAnnotArg(args) =>
buf.put('['.toByte)
buf.putShort(args.length.toShort)
for (val elem <- args) emitArgument(elem)
- case NestedAnnotationArgument(annInfo) =>
+ case NestedAnnotArg(annInfo) =>
buf.put('@'.toByte)
emitAnnotation(annInfo)
}
@@ -608,7 +609,7 @@ abstract class GenJVM extends SubComponent {
private def addRemoteException(jmethod: JMethod, meth: Symbol) {
def isRemoteThrows(ainfo: AnnotationInfo) = ainfo match {
case AnnotationInfo(tp, List(arg), _) if tp.typeSymbol == ThrowsAttr =>
- arg.intTree match {
+ arg match {
case Literal(Constant(tpe: Type)) if tpe.typeSymbol == RemoteException.typeSymbol => true
case _ => false
}
@@ -617,7 +618,8 @@ abstract class GenJVM extends SubComponent {
if (remoteClass ||
(meth.hasAnnotation(RemoteAttr) && jmethod.isPublic())) {
- val ainfo = AnnotationInfo(ThrowsAttr.tpe, List(new AnnotationArgument(Constant(RemoteException))), List())
+ val c = Constant(RemoteException)
+ val ainfo = AnnotationInfo(ThrowsAttr.tpe, List(Literal(c).setType(c.tpe)), List())
if (!meth.annotations.exists(isRemoteThrows)) {
meth.addAnnotation(ainfo)
}
diff --git a/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala b/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala
index 2b89f295d4..0871e81c5e 100644
--- a/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala
+++ b/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala
@@ -13,71 +13,34 @@ import util._
trait AnnotationInfos {
self: SymbolTable =>
- /** <p>An argument to a Scala annotation. Usually created with a
- * compiler tree representing the argument. If the tree can
- * be converted to a compile-time Constant, the method
- * <code>constant</code> returns <code>Some(c)</code>, and
- * the Pickler will write the constant to the classfile,
- * instead of the tree (optimisation).</p>
+ /** Arguments to classfile annotations (which are written to
+ * bytecode as java annotations) are either:
+ * <ul>
+ * <li>constants</li>
+ * <li>arrays of constants</li>
+ * <li>or nested classfile annotations</li>
+ * </ul>
*/
- case class AnnotationArgument(intTree: Tree) {
-
- /** This constructor is only used by the UnPickler, if it reads
- * an AnnotationArgument that was pickled as <code>Constant</code>.
- */
- def this(cons: Constant) {
- this(Literal(cons).setType(cons.tpe))
- }
-
- /** Contains <code>Some(c)</code> if the <code>intTree</code> can be
- * converted into a compile-time Constant. Used to pickle Literals
- * as Constants
- */
- val constant = intTree match {
- case Literal(c) => Some(c)
- case _ => None
- }
-
- def isConstant = !constant.isEmpty
-
- override def toString = intTree.toString
- }
-
- /** Subclasses of this class are used to represent Arguments
- * to Java-Annotations.
- */
- abstract class ConstantAnnotationArgument {
- /** A tree representing that constant. Required to store java
- * annotations in the pickle.
- */
- def toTree: Tree = this match {
- case LiteralAnnotationArgument(const) =>
- Literal(const)
- case ArrayAnnotationArgument(args) =>
- Apply(Ident("array"), args.toList map (_.toTree))
- case NestedAnnotationArgument(annInfo) =>
- Apply(Ident("annotation"), annInfo.assocs.map(asc => Assign(Ident(asc._1), asc._2.toTree))) setType annInfo.atp
- }
- }
+ abstract class ClassfileAnnotArg
/** Represents a compile-time Constant (Boolean, Byte, Short,
* Char, Int, Long, Float, Double, String, java.lang.Class or
* an instance of a Java enumeration value).
*/
- case class LiteralAnnotationArgument(const: Constant)
- extends ConstantAnnotationArgument {
+ case class LiteralAnnotArg(const: Constant)
+ extends ClassfileAnnotArg {
override def toString = const.escapedStringValue
}
- /** Represents an array of constants */
- case class ArrayAnnotationArgument(args: Array[ConstantAnnotationArgument])
- extends ConstantAnnotationArgument {
+ /** Represents an array of classfile annotation arguments */
+ case class ArrayAnnotArg(args: Array[ClassfileAnnotArg])
+ extends ClassfileAnnotArg {
override def toString = args.mkString("[", ", ", "]")
}
- /** Represents a constant nested Java annotation */
- case class NestedAnnotationArgument(annInfo: AnnotationInfo)
- extends ConstantAnnotationArgument {
+ /** Represents a nested classfile annotation */
+ case class NestedAnnotArg(annInfo: AnnotationInfo)
+ extends ClassfileAnnotArg {
// The nested annotation should not have any Scala annotation arguments
assert(annInfo.args.isEmpty, annInfo.args)
override def toString = annInfo.toString
@@ -85,49 +48,59 @@ trait AnnotationInfos {
class AnnotationInfoBase
- /** <p>Typed information about an annotation. It can be attached to
- * either a symbol or an annotated type.</p>
- * <p>Annotations are written to the classfile as Java annotations
- * if <code>atp</code> conforms to <code>ClassfileAnnotation</code>
- * (the classfile parser adds this interface to any Java annotation
- * class).</p>
- * <p>Annotations are pickled (written to scala symbtab attribute
- * in the classfile) if <code>atp</code> inherits form
- * <code>StaticAnnotation</code>.</p>
- * <p>Arguments to a Scala annotation are stored in the parameter
- * <code>args</code>. They are represented as compiler trees in
- * general, see class AnnotationInfo. Argument to Java annotaions
- * are stored as name-value pairs in <code>assocs</code>.</p>
+ /** <p>
+ * Typed information about an annotation. It can be attached to
+ * either a symbol or an annotated type.
+ * </p>
+ * <p>
+ * Annotations are written to the classfile as java annotations
+ * if <code>atp</code> conforms to <code>ClassfileAnnotation</code>
+ * (the classfile parser adds this interface to any Java annotation
+ * class).
+ * </p>
+ * <p>
+ * Annotations are pickled (written to scala symbtab attribute
+ * in the classfile) if <code>atp</code> inherits form
+ * <code>StaticAnnotation</code>.
+ * </p>
+ * <p>
+ * <code>args</code> stores arguments to Scala annotations,
+ * represented as typed trees. Note that these trees are not
+ * transformed by any phases following the type-checker.
+ * </p>
+ * <p>
+ * <code>assocs</code> stores arguments to classfile annotations
+ * as name-value pairs.
+ * </p>
*/
- case class AnnotationInfo(atp: Type, args: List[AnnotationArgument],
- assocs: List[(Name, ConstantAnnotationArgument)])
+ case class AnnotationInfo(atp: Type, args: List[Tree],
+ assocs: List[(Name, ClassfileAnnotArg)])
extends AnnotationInfoBase {
- assert(args.isEmpty || assocs.isEmpty) // Java: args empty. Scala: assocs empty.
+ // Classfile annot: args empty. Scala annot: assocs empty.
+ assert(args.isEmpty || assocs.isEmpty)
override def toString: String = atp +
(if (!args.isEmpty) args.mkString("(", ", ", ")") else "") +
(if (!assocs.isEmpty) (assocs map { case (x, y) => x+" = "+y } mkString ("(", ", ", ")")) else "")
- /** Check whether all arguments and assocations are constants */
- def isConstant = (args forall (_.isConstant))
-
/** Check whether the type or any of the arguments are erroneous */
- def isErroneous = atp.isErroneous || args.exists(_.intTree.isErroneous)
+ def isErroneous = atp.isErroneous || args.exists(_.isErroneous)
/** Check whether any of the arguments mention a symbol */
def refsSymbol(sym: Symbol) =
- args.exists(_.intTree.exists(_.symbol == sym))
+ args.exists(_.exists(_.symbol == sym))
/** Change all ident's with Symbol "from" to instead use symbol "to" */
def substIdentSyms(from: Symbol, to: Symbol) = {
val subs = new TreeSymSubstituter(List(from), List(to))
- AnnotationInfo(atp,
- args.map(arg => new AnnotationArgument(subs(arg.intTree))),
- assocs)
+ AnnotationInfo(atp, args.map(subs(_)), assocs)
}
}
- // Definition annotations parsed in Namer (typeCompleter of definitions) have to be lazy (#1782)
- case class LazyAnnotationInfo(annot: () => AnnotationInfo) extends AnnotationInfoBase
+ /** Symbol annotations parsed in Namer (typeCompleter of
+ * definitions) have to be lazy (#1782)
+ */
+ case class LazyAnnotationInfo(annot: () => AnnotationInfo)
+ extends AnnotationInfoBase
}
diff --git a/src/compiler/scala/tools/nsc/symtab/Constants.scala b/src/compiler/scala/tools/nsc/symtab/Constants.scala
index 8b372dd8b1..584eb65fdf 100644
--- a/src/compiler/scala/tools/nsc/symtab/Constants.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Constants.scala
@@ -30,7 +30,7 @@ trait Constants {
final val NullTag = LITERALnull - LITERAL
final val ClassTag = LITERALclass - LITERAL
// For supporting java enumerations inside java annotations (see ClassfileParser)
- final val EnumTag = ClassTag + 1
+ final val EnumTag = LITERALenum - LITERAL
def isNumeric(tag: Int) = ByteTag <= tag && tag <= DoubleTag
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index 8e72674dd7..eb3313a71c 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -412,10 +412,12 @@ trait Symbols {
def isDeprecated = hasAnnotation(DeprecatedAttr)
def deprecationMessage: Option[String] =
annotations find (_.atp.typeSymbol == DeprecatedAttr) flatMap { annot =>
- if (annot.args.length == 1)
- annot.args.head.constant map { c => c.stringValue }
- else
- None
+ annot.args match {
+ case Literal(const) :: Nil =>
+ Some(const.stringValue)
+ case _ =>
+ None
+ }
}
/** Does this symbol denote a wrapper object of the interpreter or its class? */
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 2e2ede998e..c78eb333af 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -2548,8 +2548,8 @@ A type's typeSymbol should never be inspected directly.
return None
val atp1 = mapOver(atp)
- val args1 = mapOverAnnotationArgs(args)
- // there is no need to rewrite assocs, as they should be constants
+ val args1 = mapOverAnnotArgs(args)
+ // there is no need to rewrite assocs, as they are constants
if ((args eq args1) && (atp eq atp1))
Some(annot)
@@ -2561,8 +2561,7 @@ A type's typeSymbol should never be inspected directly.
/** Map over a set of annotation arguments. If any
* of the arguments cannot be mapped, then return Nil. */
- def mapOverAnnotationArgs(args: List[AnnotationArgument])
- : List[AnnotationArgument] = {
+ def mapOverAnnotArgs(args: List[Tree]): List[Tree] = {
val args1 = args.flatMap(mapOver(_))
if (args1.length != args.length)
Nil
@@ -2572,23 +2571,6 @@ A type's typeSymbol should never be inspected directly.
args1
}
-
- def mapOver(arg: AnnotationArgument): Option[AnnotationArgument] = {
- if (arg.isConstant)
- Some(arg)
- else {
- mapOver(arg.intTree) match {
- case None => None
-
- case Some(tree1)
- if (tree1 eq arg.intTree) => Some(arg)
-
- case Some(tree1) => Some(new AnnotationArgument(tree1))
- }
- }
- }
-
-
def mapOver(tree: Tree): Option[Tree] =
Some(mapOver(tree, ()=>return None))
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index ca35798de4..8c49e68c25 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -764,35 +764,35 @@ abstract class ClassfileParser {
}
}
- def parseAnnotationArgument: Option[ConstantAnnotationArgument] = {
+ def parseAnnotArg: Option[ClassfileAnnotArg] = {
val tag = in.nextByte
val index = in.nextChar
tag match {
case STRING_TAG =>
- Some(LiteralAnnotationArgument(Constant(pool.getName(index).toString())))
+ Some(LiteralAnnotArg(Constant(pool.getName(index).toString())))
case BOOL_TAG | BYTE_TAG | CHAR_TAG | SHORT_TAG | INT_TAG |
LONG_TAG | FLOAT_TAG | DOUBLE_TAG =>
- Some(LiteralAnnotationArgument(pool.getConstant(index)))
+ Some(LiteralAnnotArg(pool.getConstant(index)))
case CLASS_TAG =>
- Some(LiteralAnnotationArgument(Constant(pool.getType(index))))
+ Some(LiteralAnnotArg(Constant(pool.getType(index))))
case ENUM_TAG =>
val t = pool.getType(index)
val n = pool.getName(in.nextChar)
val s = t.typeSymbol.linkedModuleOfClass.info.decls.lookup(n)
assert(s != NoSymbol, t)
- Some(LiteralAnnotationArgument(Constant(s)))
+ Some(LiteralAnnotArg(Constant(s)))
case ARRAY_TAG =>
- val arr = new ArrayBuffer[ConstantAnnotationArgument]()
+ val arr = new ArrayBuffer[ClassfileAnnotArg]()
var hasError = false
for (i <- 0 until index)
- parseAnnotationArgument match {
+ parseAnnotArg match {
case Some(c) => arr += c
case None => hasError = true
}
if (hasError) None
- else Some(ArrayAnnotationArgument(arr.toArray))
+ else Some(ArrayAnnotArg(arr.toArray))
case ANNOTATION_TAG =>
- parseAnnotation(index) map (NestedAnnotationArgument(_))
+ parseAnnotation(index) map (NestedAnnotArg(_))
}
}
@@ -802,11 +802,11 @@ abstract class ClassfileParser {
def parseAnnotation(attrNameIndex: Char): Option[AnnotationInfo] = try {
val attrType = pool.getType(attrNameIndex)
val nargs = in.nextChar
- val nvpairs = new ListBuffer[(Name,ConstantAnnotationArgument)]
+ val nvpairs = new ListBuffer[(Name, ClassfileAnnotArg)]
var hasError = false
for (i <- 0 until nargs) {
val name = pool.getName(in.nextChar)
- parseAnnotationArgument match {
+ parseAnnotArg match {
case Some(c) => nvpairs += ((name, c))
case None => hasError = true
}
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala b/src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala
index aa27b8628d..a553fdece8 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala
@@ -53,7 +53,8 @@ object PickleFormat {
* | 32 LITERALdouble len_Nat value_Long
* | 33 LITERALstring len_Nat name_Ref
* | 34 LITERALnull len_Nat
- * | 35 LITERALclass len_Nat type_Ref
+ * | 35 LITERALclass len_Nat tpe_Ref
+ * | 36 LITERALenum len_Nat sym_Ref
* | 40 SYMANNOT len_Nat sym_Ref AnnotInfoBody
* | 41 CHILDREN len_Nat sym_Ref {sym_Ref}
* | 42 ANNOTATEDtpe len_Nat [sym_Ref] tpe_Ref {annotinfo_Ref}
@@ -155,6 +156,7 @@ object PickleFormat {
final val LITERALstring = 33
final val LITERALnull = 34
final val LITERALclass = 35
+ final val LITERALenum = 36
final val SYMANNOT = 40
final val CHILDREN = 41
final val ANNOTATEDtpe = 42
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
index 9cd9e9529d..d8e645c52e 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
@@ -408,13 +408,12 @@ abstract class Pickler extends SubComponent {
/** Store a constant in map <code>index</code> along with
* anything it references.
- * No need to treat Constants with EnumTag (only used for Java
- * annotations with Java enum parameters)
*/
private def putConstant(c: Constant) {
if (putEntry(c)) {
if (c.tag == StringTag) putEntry(newTermName(c.stringValue))
else if (c.tag == ClassTag) putType(c.typeValue)
+ else if (c.tag == EnumTag) putSymbol(c.symbolValue)
}
}
@@ -442,29 +441,29 @@ abstract class Pickler extends SubComponent {
/** Puts the members of an AnnotationInfo */
private def putAnnotationBody(annot: AnnotationInfo) {
- def putAnnotationArg(arg: AnnotationArgument) {
- arg.constant match {
- case Some(c) => putConstant(c)
- case None => putTree(arg.intTree)
+ def putAnnotArg(arg: Tree) {
+ arg match {
+ case Literal(c) => putConstant(c)
+ case _ => putTree(arg)
}
}
- def putConstantAnnotationArg(carg: ConstantAnnotationArgument) {
+ def putClassfileAnnotArg(carg: ClassfileAnnotArg) {
carg match {
- case LiteralAnnotationArgument(const) =>
+ case LiteralAnnotArg(const) =>
putConstant(const)
- case ArrayAnnotationArgument(args) =>
+ case ArrayAnnotArg(args) =>
if (putEntry(carg))
- args foreach putConstantAnnotationArg
- case NestedAnnotationArgument(annInfo) =>
+ args foreach putClassfileAnnotArg
+ case NestedAnnotArg(annInfo) =>
putAnnotation(annInfo)
}
}
val AnnotationInfo(tpe, args, assocs) = annot
putType(tpe)
- args foreach putAnnotationArg
+ args foreach putAnnotArg
assocs foreach { asc =>
putEntry(asc._1)
- putConstantAnnotationArg(asc._2)
+ putClassfileAnnotArg(asc._2)
}
}
@@ -496,29 +495,29 @@ abstract class Pickler extends SubComponent {
/** Write an annotation */
private def writeAnnotation(annot: AnnotationInfo) {
- def writeAnnotationArg(arg: AnnotationArgument) {
- arg.constant match {
- case Some(c) => writeRef(c)
- case None => writeRef(arg.intTree)
+ def writeAnnotArg(arg: Tree) {
+ arg match {
+ case Literal(c) => writeRef(c)
+ case _ => writeRef(arg)
}
}
writeRef(annot.atp)
- annot.args foreach writeAnnotationArg
+ annot.args foreach writeAnnotArg
annot.assocs foreach { asc =>
writeRef(asc._1)
- writeConstantAnnotationArg(asc._2)
+ writeClassfileAnnotArg(asc._2)
}
}
- /** Write a ConstantAnnotationArgument (argument to java annotation) */
- def writeConstantAnnotationArg(carg: ConstantAnnotationArgument) {
+ /** Write a ClassfileAnnotArg (argument to classfile annotation) */
+ def writeClassfileAnnotArg(carg: ClassfileAnnotArg) {
carg match {
- case LiteralAnnotationArgument(const) =>
+ case LiteralAnnotArg(const) =>
writeRef(const)
- case ArrayAnnotationArgument(args) =>
+ case ArrayAnnotArg(args) =>
writeRef(carg)
- case NestedAnnotationArgument(annInfo) =>
+ case NestedAnnotArg(annInfo) =>
writeRef(annInfo)
}
}
@@ -584,13 +583,13 @@ abstract class Pickler extends SubComponent {
case DeBruijnIndex(l, i) =>
writeNat(l); writeNat(i); DEBRUIJNINDEXtpe
case c @ Constant(_) =>
- // No case for Constant with EnumTag. See comment on "def putConstant"
if (c.tag == BooleanTag) writeLong(if (c.booleanValue) 1 else 0)
else if (ByteTag <= c.tag && c.tag <= LongTag) writeLong(c.longValue)
else if (c.tag == FloatTag) writeLong(Float.floatToIntBits(c.floatValue))
else if (c.tag == DoubleTag) writeLong(Double.doubleToLongBits(c.doubleValue))
else if (c.tag == StringTag) writeRef(newTermName(c.stringValue))
else if (c.tag == ClassTag) writeRef(c.typeValue)
+ else if (c.tag == EnumTag) writeRef(c.symbolValue)
LITERAL + c.tag // also treats UnitTag, NullTag; no value required
case AnnotatedType(annotations, tp, selfsym) =>
val staticAnnots = staticAnnotations(annotations)
@@ -610,8 +609,8 @@ abstract class Pickler extends SubComponent {
writeAnnotation(annot)
SYMANNOT
- case ArrayAnnotationArgument(args) =>
- args foreach writeConstantAnnotationArg
+ case ArrayAnnotArg(args) =>
+ args foreach writeClassfileAnnotArg
ANNOTARGARRAY
case (target: Symbol, children: List[Symbol]) =>
@@ -955,7 +954,7 @@ abstract class Pickler extends SubComponent {
writeRefs(whereClauses)
TREE
- case Modifiers(flags, privateWithin, annotations) =>
+ case Modifiers(flags, privateWithin, _) =>
val pflags = rawFlagsToPickled(flags)
writeNat((pflags >> 32).toInt)
writeNat((pflags & 0xFFFFFFFF).toInt)
@@ -1057,6 +1056,7 @@ abstract class Pickler extends SubComponent {
else if (c.tag == DoubleTag) print("Double "+c.doubleValue)
else if (c.tag == StringTag) { print("String "); printRef(newTermName(c.stringValue)) }
else if (c.tag == ClassTag) { print("Class "); printRef(c.typeValue) }
+ else if (c.tag == EnumTag) { print("Enum "); printRef(c.symbolValue) }
case AnnotatedType(annots, tp, selfsym) =>
if (settings.selfInAnnots.value) {
print("ANNOTATEDWSELFtpe ")
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
index 1db8304e9b..f5aa4ed41b 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
@@ -350,6 +350,7 @@ abstract class UnPickler {
case LITERALstring => Constant(readNameRef().toString())
case LITERALnull => Constant(null)
case LITERALclass => Constant(readTypeRef())
+ case LITERALenum => Constant(readSymbolRef())
case _ => errorBadSignature("bad constant tag: " + tag)
}
}
@@ -364,31 +365,30 @@ abstract class UnPickler {
while (readIndex != end) target addChild readSymbolRef()
}
- /** Read an annotation argument. It can use either Constant's or
- * Tree's for its arguments.
+ /** Read an annotation argument, which is pickled either
+ * as a Constant or a Tree.
*/
- private def readAnnotationArg(): AnnotationArgument = {
+ private def readAnnotArg(): Tree = {
if (peekByte() == TREE) {
- val tree = readTree()
- new AnnotationArgument(tree)
+ readTree()
} else {
val const = readConstant()
- new AnnotationArgument(const)
+ Literal(const).setType(const.tpe)
}
}
- /** Read a ConstantAnnotationArgument (argument to a java annotation)
+ /** Read a ClassfileAnnotArg (argument to a classfile annotation)
*/
- private def readConstantAnnotationArg(): ConstantAnnotationArgument = {
+ private def readClassfileAnnotArg(): ClassfileAnnotArg = {
val b = peekByte()
if (peekByte() == ANNOTINFO) {
- NestedAnnotationArgument(readAnnotation())
+ NestedAnnotArg(readAnnotation())
} else if (peekByte() == ANNOTARGARRAY) {
readByte()
val end = readNat() + readIndex
- ArrayAnnotationArgument(until(end, readConstantAnnotationArgRef).toArray)
+ ArrayAnnotArg(until(end, readClassfileAnnotArgRef).toArray)
} else {
- LiteralAnnotationArgument(readConstant())
+ LiteralAnnotArg(readConstant())
}
}
@@ -397,16 +397,14 @@ abstract class UnPickler {
*/
private def readAnnotationInfo(end: Int): AnnotationInfo = {
val atp = readTypeRef()
- //val args = until(end, readAnnotationArgRef)
- //AnnotationInfo(atp, args, List())
- val args = new ListBuffer[AnnotationArgument]
- val assocs = new ListBuffer[(Name, ConstantAnnotationArgument)]
+ val args = new ListBuffer[Tree]
+ val assocs = new ListBuffer[(Name, ClassfileAnnotArg)]
while (readIndex != end) {
val argref = readNat()
if (isNameEntry(argref))
- assocs += ((at(argref, readName), readConstantAnnotationArgRef))
+ assocs += ((at(argref, readName), readClassfileAnnotArgRef))
else
- args += at(argref, readAnnotationArg)
+ args += at(argref, readAnnotArg)
}
AnnotationInfo(atp, args.toList, assocs.toList)
}
@@ -424,8 +422,8 @@ abstract class UnPickler {
target.addAnnotation(readAnnotationInfo(end))
}
- /** Read an annotation and return it. Only called when
- * unpickling an ANNOTATED(WSELF)tpe. */
+ /** Read an annotation and return it. Used when unpickling
+ * an ANNOTATED(WSELF)tpe or a NestedAnnotArg */
private def readAnnotation(): AnnotationInfo = {
val tag = readByte()
if (tag != ANNOTINFO)
@@ -752,10 +750,10 @@ abstract class UnPickler {
private def readSymbolRef(): Symbol = at(readNat(), readSymbol)
private def readTypeRef(): Type = at(readNat(), readType)
private def readConstantRef(): Constant = at(readNat(), readConstant)
- private def readAnnotationArgRef(): AnnotationArgument =
- at(readNat(), readAnnotationArg)
- private def readConstantAnnotationArgRef(): ConstantAnnotationArgument =
- at(readNat(), readConstantAnnotationArg)
+ private def readAnnotArgRef(): Tree =
+ at(readNat(), readAnnotArg)
+ private def readClassfileAnnotArgRef(): ClassfileAnnotArg =
+ at(readNat(), readClassfileAnnotArg)
private def readAnnotationRef(): AnnotationInfo =
at(readNat(), readAnnotation)
private def readModifiersRef(): Modifiers =
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 626dbe00bd..5f490592f5 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -768,7 +768,7 @@ trait Namers { self: Analyzer =>
}
}
- // AnnotatedTypes can contain trees in the AnnotationArguments. When accessing a
+ // AnnotatedTypes can contain trees in the annotation arguments. When accessing a
// parameter in an annotation, set the type of the Ident to the DeBruijnIndex
object treeTrans extends TypeMapTransformer {
override def transform(tree: Tree): Tree =
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index c11b157208..2015716aae 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -846,11 +846,11 @@ abstract class RefChecks extends InfoTransform {
tree match {
case m: MemberDef =>
checkAnnotations(m.symbol.annotations.map(a => (a.atp, tree.pos)))
- transformTrees(m.symbol.annotations.flatMap(a => a.args.map(_.intTree)))
+ transformTrees(m.symbol.annotations.flatMap(_.args))
case TypeTree() => doTypeTraversal {
case AnnotatedType(annots, _, _) =>
checkAnnotations(annots.map(a => (a.atp, tree.pos)))
- transformTrees(annots.flatMap(a => a.args.map(_.intTree)))
+ transformTrees(annots.flatMap(_.args))
case _ =>
}
case _ =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 4255fd54e2..2e8032d10a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -2035,7 +2035,7 @@ trait Typers { self: Analyzer =>
else {
assert(isNamedApplyBlock(fun1), fun1)
val NamedApplyInfo(qual, targs, previousArgss, _) =
- context.namedApplyBlockInfo.get._2
+ context.namedApplyBlockInfo.get._2
val (allArgs, missing) = addDefaults(args, qual, targs, previousArgss, mt.params)
if (allArgs.length == formals.length) {
// a default for each missing argument was found
@@ -2279,17 +2279,17 @@ trait Typers { self: Analyzer =>
None
}
- /** Converts an untyped tree to a ConstantAnnotationArgument. If the conversion fails,
+ /** Converts an untyped tree to a ClassfileAnnotArg. If the conversion fails,
* an error message is reporded and None is returned.
*/
- def tree2ConstArg(tree: Tree, pt: Type): Option[ConstantAnnotationArgument] = tree match {
+ def tree2ConstArg(tree: Tree, pt: Type): Option[ClassfileAnnotArg] = tree match {
case ann @ Apply(Select(New(tpt), nme.CONSTRUCTOR), args) =>
val annInfo = typedAnnotation(ann, mode, NoSymbol, pt.typeSymbol, true)
if (annInfo.atp.isErroneous) {
// recursive typedAnnotation call already printed an error, so don't call "error"
hasError = true
None
- } else Some(NestedAnnotationArgument(annInfo))
+ } else Some(NestedAnnotArg(annInfo))
// use of: object Array.apply[A <: AnyRef](args: A*): Array[A] = ...
// and object Array.apply(args: Int*): Array[Int] = ... (and similar)
@@ -2307,18 +2307,17 @@ trait Typers { self: Analyzer =>
case tree => typed(tree, EXPRmode, pt) match {
case l @ Literal(c) if !l.isErroneous =>
- Some(LiteralAnnotationArgument(c))
+ Some(LiteralAnnotArg(c))
case _ =>
needConst(tree)
}
}
- def trees2ConstArg(trees: List[Tree], pt: Type): Option[ArrayAnnotationArgument] = {
+ def trees2ConstArg(trees: List[Tree], pt: Type): Option[ArrayAnnotArg] = {
val args = trees.map(tree2ConstArg(_, pt))
if (args.exists(_.isEmpty)) None
- else Some(ArrayAnnotationArgument(args.map(_.get).toArray))
+ else Some(ArrayAnnotArg(args.map(_.get).toArray))
}
-
// begin typedAnnotation
val (fun, argss) = {
def extract(fun: Tree, outerArgss: List[List[Tree]]):
@@ -2424,7 +2423,7 @@ trait Typers { self: Analyzer =>
def annInfo(t: Tree): AnnotationInfo = t match {
case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) =>
- AnnotationInfo(annType, args.map(AnnotationArgument(_)), List())
+ AnnotationInfo(annType, args, List())
case Block(stats, expr) =>
context.warning(t.pos, "Usage of named or default arguments transformed this annotation\n"+
@@ -2581,15 +2580,15 @@ trait Typers { self: Analyzer =>
case ExistentialType(tparams, _) =>
boundSyms ++= tparams
case AnnotatedType(annots, _, _) =>
- for (annot <- annots; arg <- annot.args; t <- arg.intTree) {
- t match {
+ for (annot <- annots; arg <- annot.args) {
+ arg match {
case Ident(_) =>
// Check the symbol of an Ident, unless the
// Ident's type is already over an existential.
// (If the type is already over an existential,
// then remap the type, not the core symbol.)
- if (!t.tpe.typeSymbol.hasFlag(EXISTENTIAL))
- addIfLocal(t.symbol, t.tpe)
+ if (!arg.tpe.typeSymbol.hasFlag(EXISTENTIAL))
+ addIfLocal(arg.symbol, arg.tpe)
case _ => ()
}
}
diff --git a/test/files/pos/t1782/Ann.java b/test/files/pos/t1782/Ann.java
new file mode 100644
index 0000000000..cd3b2b33ca
--- /dev/null
+++ b/test/files/pos/t1782/Ann.java
@@ -0,0 +1,3 @@
+public @interface Ann {
+ public Days value();
+} \ No newline at end of file
diff --git a/test/files/pos/t1782/Days.java b/test/files/pos/t1782/Days.java
new file mode 100644
index 0000000000..b0d1ac4902
--- /dev/null
+++ b/test/files/pos/t1782/Days.java
@@ -0,0 +1,3 @@
+public enum Days {
+ Friday, Sunday
+} \ No newline at end of file
diff --git a/test/files/pos/t1782/Test_1.scala b/test/files/pos/t1782/Test_1.scala
index de4f0e9886..021dfc6d53 100644
--- a/test/files/pos/t1782/Test_1.scala
+++ b/test/files/pos/t1782/Test_1.scala
@@ -6,5 +6,6 @@ trait Service {
class Provider
extends Service
{
- def someMethod() = ()
+ // test enumeration java annotations
+ @Ann(Days.Friday) def someMethod() = ()
}