diff --git a/src/compiler/scala/reflect/internal/StdNames.scala b/src/compiler/scala/reflect/internal/StdNames.scala index 0cdf65bd8f72..bd4d9a9f3486 100644 --- a/src/compiler/scala/reflect/internal/StdNames.scala +++ b/src/compiler/scala/reflect/internal/StdNames.scala @@ -766,7 +766,6 @@ trait StdNames { object fulltpnme extends TypeNames { val RuntimeNothing: NameType = "scala.runtime.Nothing$" val RuntimeNull: NameType = "scala.runtime.Null$" - val JavaLangEnum: NameType = "java.lang.Enum" } /** Java binary names, like scala/runtime/Nothing$. diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index 5c413243e8e2..f71e0673662e 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -872,7 +872,10 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { skipAhead() accept(RBRACE) } - ValDef(Modifiers(Flags.JAVA | Flags.STATIC), name, enumType, blankExpr) + // The STABLE flag is to signal to namer that this was read from a + // java enum, and so should be given a Constant type (thereby making + // it usable in annotations.) + ValDef(Modifiers(Flags.STABLE | Flags.JAVA | Flags.STATIC), name, enumType, blankExpr) } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index ca4b1d3de8bd..e4b744dffc1e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -567,7 +567,15 @@ trait Namers extends MethodSynthesis { assignAndEnterFinishedSymbol(tree) else enterGetterSetter(tree) + + // When java enums are read from bytecode, they are known to have + // constant types by the jvm flag and assigned accordingly. When + // they are read from source, the java parser marks them with the + // STABLE flag, and now we receive that signal. + if (tree.symbol hasAllFlags STABLE | JAVA) + tree.symbol setInfo ConstantType(Constant(tree.symbol)) } + def enterLazyVal(tree: ValDef, lazyAccessor: Symbol): TermSymbol = { // If the owner is not a class, this is a lazy val from a method, // with no associated field. It has an accessor with $lzy appended to its name and diff --git a/test/files/pos/t2764/Ann.java b/test/files/pos/t2764/Ann.java new file mode 100644 index 000000000000..184fc6e864c2 --- /dev/null +++ b/test/files/pos/t2764/Ann.java @@ -0,0 +1,5 @@ +package bippy; + +public @interface Ann { + Enum value(); +} diff --git a/test/files/pos/t2764/Enum.java b/test/files/pos/t2764/Enum.java new file mode 100644 index 000000000000..fe0755953548 --- /dev/null +++ b/test/files/pos/t2764/Enum.java @@ -0,0 +1,5 @@ +package bippy; + +public enum Enum { + VALUE; +} diff --git a/test/files/pos/t2764/Use.scala b/test/files/pos/t2764/Use.scala new file mode 100644 index 000000000000..8cf810270944 --- /dev/null +++ b/test/files/pos/t2764/Use.scala @@ -0,0 +1,6 @@ +package bippy + +class Use { + @Ann(Enum.VALUE) + def foo {} +}