summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Constants.scala7
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala23
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala2
-rw-r--r--test/files/jvm/t2470.check1
-rw-r--r--test/files/jvm/t2470/Action.java6
-rw-r--r--test/files/jvm/t2470/Read_Classfile_2.scala3
-rw-r--r--test/files/jvm/t2470/Task.java3
-rw-r--r--test/files/jvm/t2470/Test_1.scala11
8 files changed, 51 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Constants.scala b/src/compiler/scala/tools/nsc/symtab/Constants.scala
index dfe7147270..2a4d3e1fa1 100644
--- a/src/compiler/scala/tools/nsc/symtab/Constants.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Constants.scala
@@ -66,7 +66,12 @@ trait Constants {
case StringTag => StringClass.tpe
case NullTag => NullClass.tpe
case ClassTag => Predef_classOfType(value.asInstanceOf[Type])
- case EnumTag => symbolValue.owner.linkedClassOfClass.tpe
+ case EnumTag =>
+ // given (in java): "class A { enum E { VAL1 } }"
+ // - symbolValue: the symbol of the actual enumeration value (VAL1)
+ // - .owner: the ModuleClasSymbol of the enumeration (object E)
+ // - .linkedClassOfClass: the ClassSymbol of the enumeration (class E)
+ symbolValue.owner.linkedClassOfClass.tpe
}
/** We need the equals method to take account of tags as well as values.
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index 3b9ffa4f58..1c22a6fdaf 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -1235,7 +1235,7 @@ trait Symbols {
*/
final def linkedClassOfModule: Symbol = {
if (this != NoSymbol)
- owner.rawInfo.decl(name.toTypeName).suchThat(_ isCoDefinedWith this)
+ flatOwnerInfo.decl(name.toTypeName).suchThat(_ isCoDefinedWith this)
else NoSymbol
}
@@ -1244,7 +1244,7 @@ trait Symbols {
*/
final def linkedModuleOfClass: Symbol =
if (this.isClass && !this.isAnonymousClass && !this.isRefinementClass) {
- owner.rawInfo.decl(name.toTermName).suchThat(
+ flatOwnerInfo.decl(name.toTermName).suchThat(
sym => (sym hasFlag MODULE) && (sym isCoDefinedWith this))
} else NoSymbol
@@ -1253,7 +1253,7 @@ trait Symbols {
*/
final def linkedSym: Symbol =
if (isTerm) linkedClassOfModule
- else if (isClass) owner.rawInfo.decl(name.toTermName).suchThat(_ isCoDefinedWith this)
+ else if (isClass) flatOwnerInfo.decl(name.toTermName).suchThat(_ isCoDefinedWith this)
else NoSymbol
/** For a module class its linked class, for a plain class
@@ -1268,6 +1268,23 @@ trait Symbols {
final def linkedClassOfClass: Symbol =
if (isModuleClass) linkedClassOfModule else linkedModuleOfClass.moduleClass
+ /**
+ * Returns the rawInfo of the owner. If the current phase has flat classes, it first
+ * applies all pending type maps to this symbol.
+ *
+ * Asssume this is the ModuleSymbol for B in the follwing definition:
+ * package p { class A { object B { val x = 1 } } }
+ *
+ * The owner after flatten is "package p" (see "def owner"). The flatten type map enters
+ * symbol B in the decls of p. So to find a linked symbol ("object B" or "class B")
+ * we need to apply flatten to B first. Fixes #2470.
+ */
+ private final def flatOwnerInfo: Type = {
+ if (phase.flatClasses && rawowner != NoSymbol && !rawowner.isPackageClass)
+ info
+ owner.rawInfo
+ }
+
/** If this symbol is an implementation class, its interface, otherwise the symbol itself
* The method follows two strategies to determine the interface.
* - during or after erasure, it takes the last parent of the implementatation class
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 940a8e223b..86cb636fb8 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -890,7 +890,7 @@ abstract class ClassfileParser {
val innerClass = getOwner(jflags).newClass(NoPosition, name.toTypeName).setInfo(completer).setFlag(sflags)
val innerModule = getOwner(jflags).newModule(NoPosition, name).setInfo(completer).setFlag(sflags)
- innerClass.moduleClass.setInfo(global.loaders.moduleClassLoader)
+ innerModule.moduleClass.setInfo(global.loaders.moduleClassLoader)
getScope(jflags).enter(innerClass)
getScope(jflags).enter(innerModule)
diff --git a/test/files/jvm/t2470.check b/test/files/jvm/t2470.check
new file mode 100644
index 0000000000..11539b2a9f
--- /dev/null
+++ b/test/files/jvm/t2470.check
@@ -0,0 +1 @@
+List(@Action(block=ACTION))
diff --git a/test/files/jvm/t2470/Action.java b/test/files/jvm/t2470/Action.java
new file mode 100644
index 0000000000..62c71c43f1
--- /dev/null
+++ b/test/files/jvm/t2470/Action.java
@@ -0,0 +1,6 @@
+import java.lang.annotation.*;
+
+@Retention(value=RetentionPolicy.RUNTIME)
+public @interface Action {
+ Task.Scope block() default Task.Scope.ACTION;
+}
diff --git a/test/files/jvm/t2470/Read_Classfile_2.scala b/test/files/jvm/t2470/Read_Classfile_2.scala
new file mode 100644
index 0000000000..07961776dd
--- /dev/null
+++ b/test/files/jvm/t2470/Read_Classfile_2.scala
@@ -0,0 +1,3 @@
+class Read {
+ val t = Test
+}
diff --git a/test/files/jvm/t2470/Task.java b/test/files/jvm/t2470/Task.java
new file mode 100644
index 0000000000..64004b5867
--- /dev/null
+++ b/test/files/jvm/t2470/Task.java
@@ -0,0 +1,3 @@
+class Task {
+ public enum Scope { ACTION, HIKA }
+}
diff --git a/test/files/jvm/t2470/Test_1.scala b/test/files/jvm/t2470/Test_1.scala
new file mode 100644
index 0000000000..00cf287482
--- /dev/null
+++ b/test/files/jvm/t2470/Test_1.scala
@@ -0,0 +1,11 @@
+object Test {
+ class Foo {
+ @Action(block = Task.Scope.ACTION)
+ def foo = 0
+ }
+
+ def main(args: Array[String]) {
+ val m = classOf[Foo].getDeclaredMethods().find(_.toString.contains("foo")).get
+ println(m.getAnnotations().toList)
+ }
+}