diff --git a/compiler/src/dotty/tools/dotc/Compiler.scala b/compiler/src/dotty/tools/dotc/Compiler.scala index 32cee5faaa3f..8f4ab656881b 100644 --- a/compiler/src/dotty/tools/dotc/Compiler.scala +++ b/compiler/src/dotty/tools/dotc/Compiler.scala @@ -58,8 +58,8 @@ class Compiler { new CheckReentrant, // Internal use only: Check that compiled program has no data races involving global vars new ElimPackagePrefixes, // Eliminate references to package prefixes in Select nodes new CookComments, // Cook the comments: expand variables, doc, etc. - new CompleteJavaEnums) :: // Fill in constructors for Java enums - List(new CheckStatic, // Check restrictions that apply to @static members + new CheckStatic) :: // Check restrictions that apply to @static members + List(new CompleteJavaEnums, // Fill in constructors for Java enums new ElimRepeated, // Rewrite vararg parameters and arguments new ExpandSAMs, // Expand single abstract method closures to anonymous classes new ProtectedAccessors, // Add accessors for protected members diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileConstants.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileConstants.scala index 02cebe2541ab..b57404a77377 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileConstants.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileConstants.scala @@ -343,6 +343,7 @@ object ClassfileConstants { case JAVA_ACC_FINAL => Final case JAVA_ACC_SYNTHETIC => Synthetic case JAVA_ACC_STATIC => JavaStatic + case JAVA_ACC_ENUM => Enum case JAVA_ACC_ABSTRACT => if (isClass) Abstract else Deferred case JAVA_ACC_INTERFACE => PureInterfaceCreationFlags | JavaDefined case _ => EmptyFlags diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala index 966ccb90cbdd..6b85cec70d7a 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala @@ -200,12 +200,10 @@ class ClassfileParser( sym.markAbsent() } - // eager load java enum definitions for exhaustivity check of pattern match + // eager load enum definitions for exhaustivity check of pattern match if (isEnum) { instanceScope.toList.map(_.ensureCompleted()) staticScope.toList.map(_.ensureCompleted()) - classRoot.setFlag(Flags.JavaEnumTrait) - moduleRoot.setFlag(Flags.JavaEnumTrait) } result diff --git a/compiler/src/dotty/tools/dotc/transform/CompleteJavaEnums.scala b/compiler/src/dotty/tools/dotc/transform/CompleteJavaEnums.scala index 75f5d453fe5a..eed261f62115 100644 --- a/compiler/src/dotty/tools/dotc/transform/CompleteJavaEnums.scala +++ b/compiler/src/dotty/tools/dotc/transform/CompleteJavaEnums.scala @@ -110,11 +110,20 @@ class CompleteJavaEnums extends MiniPhase with InfoTransformer { thisPhase => else tree } - override def transformValDef(tree: ValDef)(implicit ctx: Context): ValDef = { - val sym = tree.symbol - if ((sym.isAllOf(EnumValue) || sym.name == nme.DOLLAR_VALUES) && sym.owner.linkedClass.derivesFromJavaEnum) - sym.addAnnotation(Annotations.Annotation(defn.ScalaStaticAnnot)) - tree + /** Return a list of forwarders for enum values defined in the companion object + * for java interop. + */ + private def addedEnumForwarders(clazz: Symbol)(implicit ctx: Context): List[ValDef] = { + val moduleCls = clazz.companionClass + val moduleRef = ref(clazz.companionModule) + + val enums = moduleCls.info.decls.filter(member => member.isAllOf(EnumValue)) + for { enumValue <- enums } + yield { + val fieldSym = ctx.newSymbol(clazz, enumValue.name.asTermName, EnumValue | JavaStatic, enumValue.info) + fieldSym.addAnnotation(Annotations.Annotation(defn.ScalaStaticAnnot)) + ValDef(fieldSym, moduleRef.select(enumValue)) + } } /** 1. If this is an enum class, add $name and $ordinal parameters to its @@ -143,9 +152,10 @@ class CompleteJavaEnums extends MiniPhase with InfoTransformer { thisPhase => val (params, rest) = decomposeTemplateBody(templ.body) val addedDefs = addedParams(cls, ParamAccessor) val addedSyms = addedDefs.map(_.symbol.entered) + val addedForwarders = addedEnumForwarders(cls) cpy.Template(templ)( parents = addEnumConstrArgs(defn.JavaEnumClass, templ.parents, addedSyms.map(ref)), - body = params ++ addedDefs ++ rest) + body = params ++ addedDefs ++ addedForwarders ++ rest) } else if (cls.isAnonymousClass && cls.owner.isAllOf(EnumCase) && cls.owner.owner.linkedClass.derivesFromJavaEnum) { def rhsOf(name: TermName) = diff --git a/compiler/test-resources/repl/i7410 b/compiler/test-resources/repl/i7410 new file mode 100644 index 000000000000..1f48a4c52f05 --- /dev/null +++ b/compiler/test-resources/repl/i7410 @@ -0,0 +1,4 @@ +scala> enum E { case A, B, C } +// defined class E +scala> E.A +val res0: E = A \ No newline at end of file diff --git a/tests/run/i6664/Bomb_1.scala b/tests/run/i6664/Bomb_1.scala new file mode 100644 index 000000000000..fb1603635ef0 --- /dev/null +++ b/tests/run/i6664/Bomb_1.scala @@ -0,0 +1,4 @@ +enum Bomb +{ + case Kaboom +} \ No newline at end of file diff --git a/tests/run/i6664/Detonator_2.scala b/tests/run/i6664/Detonator_2.scala new file mode 100644 index 000000000000..690780d47d4f --- /dev/null +++ b/tests/run/i6664/Detonator_2.scala @@ -0,0 +1,5 @@ +object Test +{ + def boom: Unit = Bomb.valueOf("Kaboom") + def main(args: Array[String]): Unit = println("ok!") +} \ No newline at end of file diff --git a/tests/run/i6664b/Bomb_1.scala b/tests/run/i6664b/Bomb_1.scala new file mode 100644 index 000000000000..e50d06ab1d0e --- /dev/null +++ b/tests/run/i6664b/Bomb_1.scala @@ -0,0 +1,4 @@ +enum Bomb extends java.lang.Enum[Bomb] +{ + case Kaboom +} \ No newline at end of file diff --git a/tests/run/i6664b/Detonator_2.scala b/tests/run/i6664b/Detonator_2.scala new file mode 100644 index 000000000000..4c4c74a24eed --- /dev/null +++ b/tests/run/i6664b/Detonator_2.scala @@ -0,0 +1,4 @@ +object Test +{ + def main(args: Array[String]): Unit = println(Bomb.Kaboom) +} \ No newline at end of file diff --git a/tests/run/i6677/Enum_1.scala b/tests/run/i6677/Enum_1.scala new file mode 100644 index 000000000000..260f450686fb --- /dev/null +++ b/tests/run/i6677/Enum_1.scala @@ -0,0 +1,3 @@ +enum Foo[A] { + case Bar extends Foo[Int] +} diff --git a/tests/run/i6677/Test_2.scala b/tests/run/i6677/Test_2.scala new file mode 100644 index 000000000000..62f77cc4d27e --- /dev/null +++ b/tests/run/i6677/Test_2.scala @@ -0,0 +1,5 @@ +object Test { + def main(args: Array[String]): Unit = { + println(Foo.Bar) + } +} \ No newline at end of file diff --git a/tests/run/i7287/Enum_1.scala b/tests/run/i7287/Enum_1.scala new file mode 100644 index 000000000000..94ce29fa206b --- /dev/null +++ b/tests/run/i7287/Enum_1.scala @@ -0,0 +1,5 @@ +enum Color derives Eql { + case Unknown + case Blue(v: Int) + case Red(v: Int) +} diff --git a/tests/run/i7287/Test_2.scala b/tests/run/i7287/Test_2.scala new file mode 100644 index 000000000000..8f3fabf18dc5 --- /dev/null +++ b/tests/run/i7287/Test_2.scala @@ -0,0 +1,6 @@ +object Test { + def main(args: Array[String]): Unit = { + val testData = Seq(("blah", Color.Unknown), ("red", Color.Red(10))) + println(testData) + } +} \ No newline at end of file diff --git a/tests/run/i7410/Enum_1.scala b/tests/run/i7410/Enum_1.scala new file mode 100644 index 000000000000..228bb3699c4f --- /dev/null +++ b/tests/run/i7410/Enum_1.scala @@ -0,0 +1,3 @@ +enum E { + case A, B, C +} diff --git a/tests/run/i7410/Test_2.scala b/tests/run/i7410/Test_2.scala new file mode 100644 index 000000000000..a2e22261a4a6 --- /dev/null +++ b/tests/run/i7410/Test_2.scala @@ -0,0 +1,6 @@ +object Test { + def main(args: Array[String]): Unit = { + val a = E.A + println(a) + } +} \ No newline at end of file diff --git a/tests/run/i7424/Enum_1.scala b/tests/run/i7424/Enum_1.scala new file mode 100644 index 000000000000..7b19fc5b6eba --- /dev/null +++ b/tests/run/i7424/Enum_1.scala @@ -0,0 +1,3 @@ +enum A { + case A1 +} diff --git a/tests/run/i7424/Test_2.scala b/tests/run/i7424/Test_2.scala new file mode 100644 index 000000000000..cc3b5fbdac7f --- /dev/null +++ b/tests/run/i7424/Test_2.scala @@ -0,0 +1,5 @@ +object Test { + def main(args: Array[String]): Unit = { + println(A.values) + } +} \ No newline at end of file diff --git a/tests/run/i7991.scala b/tests/run/i7991.scala new file mode 100644 index 000000000000..27ba1e64cc53 --- /dev/null +++ b/tests/run/i7991.scala @@ -0,0 +1,5 @@ +enum Num { case One } + +object Test extends App { + Num.One +} \ No newline at end of file diff --git a/tests/run/i7991/Num_1.scala b/tests/run/i7991/Num_1.scala new file mode 100644 index 000000000000..cc35f91c9dab --- /dev/null +++ b/tests/run/i7991/Num_1.scala @@ -0,0 +1 @@ +enum Num { case One } \ No newline at end of file diff --git a/tests/run/i7991/Test_2.scala b/tests/run/i7991/Test_2.scala new file mode 100644 index 000000000000..14e4fb704344 --- /dev/null +++ b/tests/run/i7991/Test_2.scala @@ -0,0 +1,3 @@ +object Test extends App { + Num.One +}