From 2dcd64a35d5b56473e68c509e8738e53361a2069 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 4 Dec 2023 10:01:51 +0100 Subject: [PATCH] Improve failure message of enum `fromOrdinal`/`valueOf` Fixes #19178 --- .../src/dotty/tools/dotc/ast/DesugarEnums.scala | 5 +++-- tests/run/enum-java.check | 2 +- tests/run/enum-values.scala | 2 +- tests/run/enums-java-compat.check | 2 +- tests/run/i19178.check | 4 ++++ tests/run/i19178.scala | 14 ++++++++++++++ 6 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 tests/run/i19178.check create mode 100644 tests/run/i19178.scala diff --git a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala index 4b00f72bf21e..98873dba85c7 100644 --- a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala +++ b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala @@ -126,7 +126,7 @@ object DesugarEnums { val valuesOfBody: Tree = val defaultCase = - val msg = Apply(Select(Literal(Constant("enum case not found: ")), nme.PLUS), Ident(nme.nameDollar)) + val msg = Apply(Select(Literal(Constant(s"enum ${enumClass.fullName} has no case with name: ")), nme.PLUS), Ident(nme.nameDollar)) CaseDef(Ident(nme.WILDCARD), EmptyTree, Throw(New(TypeTree(defn.IllegalArgumentExceptionType), List(msg :: Nil)))) val stringCases = enumValues.map(enumValue => @@ -148,7 +148,8 @@ object DesugarEnums { def valueCtor: List[Tree] = if constraints.requiresCreator then enumValueCreator :: Nil else Nil def fromOrdinal: Tree = def throwArg(ordinal: Tree) = - Throw(New(TypeTree(defn.NoSuchElementExceptionType), List(Select(ordinal, nme.toString_) :: Nil))) + val msg = Apply(Select(Literal(Constant(s"enum ${enumClass.fullName} has no case with ordinal: ")), nme.PLUS), Select(ordinal, nme.toString_)) + Throw(New(TypeTree(defn.NoSuchElementExceptionType), List(msg :: Nil))) if !constraints.cached then fromOrdinalMeth(throwArg) else diff --git a/tests/run/enum-java.check b/tests/run/enum-java.check index 667e6a4df37c..ad609d5bfe22 100644 --- a/tests/run/enum-java.check +++ b/tests/run/enum-java.check @@ -26,7 +26,7 @@ MONDAY : 0 TUESDAY : 1 SATURDAY : 2 By-name value: MONDAY -Correctly failed to retrieve illegal name, message: enum case not found: stuff +Correctly failed to retrieve illegal name, message: enum A has no case with name: stuff Collections Test Retrieving Monday: workday diff --git a/tests/run/enum-values.scala b/tests/run/enum-values.scala index 41543e196561..51ad2467b1c8 100644 --- a/tests/run/enum-values.scala +++ b/tests/run/enum-values.scala @@ -61,7 +61,7 @@ enum ClassOnly: // this should still generate the `ordinal` and `fromOrdinal` co catch case e: java.lang.reflect.InvocationTargetException => // TODO: maybe reflect.Selectable should catch this? assert(e.getCause.isInstanceOf[java.util.NoSuchElementException] - && e.getCause.getMessage == ordinal.toString) + && e.getCause.getMessage == s"enum ${companion.getClass.getName.stripSuffix("$")} has no case with ordinal: $ordinal") fetchFromOrdinal(companion = Color, compare = Red, Green, Blue) fetchFromOrdinal(companion = Suits, compare = Clubs, Spades, Diamonds, Hearts) diff --git a/tests/run/enums-java-compat.check b/tests/run/enums-java-compat.check index 0acf636fe377..df26b421acba 100644 --- a/tests/run/enums-java-compat.check +++ b/tests/run/enums-java-compat.check @@ -6,4 +6,4 @@ TUESDAY : 1 SATURDAY : 2 Stuff : 3 By-name value: MONDAY -Correctly failed to retrieve illegal name, message: enum case not found: stuff +Correctly failed to retrieve illegal name, message: enum A has no case with name: stuff diff --git a/tests/run/i19178.check b/tests/run/i19178.check new file mode 100644 index 000000000000..e948c0f7dd15 --- /dev/null +++ b/tests/run/i19178.check @@ -0,0 +1,4 @@ +Failure(java.util.NoSuchElementException: enum Foo has no case with ordinal: 3) +Failure(java.lang.IllegalArgumentException: enum Foo has no case with name: Bar) +Failure(java.util.NoSuchElementException: enum bar.Bar has no case with ordinal: 4) +Failure(java.lang.IllegalArgumentException: enum bar.Bar has no case with name: Baz) diff --git a/tests/run/i19178.scala b/tests/run/i19178.scala new file mode 100644 index 000000000000..ba38f4f933b0 --- /dev/null +++ b/tests/run/i19178.scala @@ -0,0 +1,14 @@ +enum Foo: + case A + +package bar { + enum Bar: + case B +} + +@main def Test = + import scala.util.Try + println(Try(Foo.fromOrdinal(3))) + println(Try(Foo.valueOf("Bar"))) + println(Try(bar.Bar.fromOrdinal(4))) + println(Try(bar.Bar.valueOf("Baz")))