-
Notifications
You must be signed in to change notification settings - Fork 1.1k
fix #7227: allow custom toString on enum #9549
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix #7227: allow custom toString on enum #9549
Conversation
0dd4b22
to
d3cf186
Compare
compiler/src/dotty/tools/dotc/transform/CompleteJavaEnums.scala
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find productPrefix
much less user-friendly than name
, especially since the latter is familiar for users coming from Python, Java, Kotlin and probably more. It can also be surprising that name
is the only method that requires extends java.lang.Enum
to be available. You can call ordinal
, productPrefix
, etc. on all enums but not name
.
Could name
be handled in a similar way to toString
, i.e. redirect to productPrefix
for pure-dotty enums and to the name
method for java enums?
@TheElectronWill enum User:
case Basic(name: String)
case Unknown we won't be able to define a field it could potentially be added to concrete enums if they have no parameterised cases, but then that API is again not generic unless we make a new mixin trait. We can definitely explore options though, like do the above and have an annotation to force checking of only value cases, or a type class that adds an extension and does the same checking |
Doesn't |
Thats true, but I do suspect I'll try an implementation with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but it'd be good to make a summary of all these enum changes and start a discussion in https://contributors.scala-lang.org/ to inform everyone about them.
c761e90
to
eefc1ff
Compare
rebased |
productPrefix is now overriden using the enum constant's name and used in the by-name lookup in EnumValues. java based enum values are optimised so that productPrefix will forward to .name in the simple enum case, avoiding an extra field
As a rule, even class cases override it to be consistent with singleton cases which must have a value matching the identifier. this also moves runtime.EnumValues into src-bootstrapped so that fromName can directly call .enumLabel This commit also removes the forced override of productPrefix in EnumValue and individial cases, this allows the user to customise productPrefix as with typical case classes. An override of productPrefix will be generated in SyntheticMembers to forward to enumLabel if a class parent does not define one.
eefc1ff
to
9c9db17
Compare
rebased again |
I agree. An alternative solution would be to synthesize a method enum Foo:
case Bar, Baz Desugars to: sealed trait Foo
object Foo:
case object Bar extends Foo
case object Baz extends Foo
def ordinal(value: Foo): Int =
value match:
case Bar => 0
case Baz => 1
end Foo (the same could be done with My second idea is to drop the support for enum cases that are not singleton values. (this also solves the problem of |
@julienrf so that ordinal method is already generated for the Mirror framework, and so that could definitely be enhanced for case label too, and so we're less likely to have method name collisions, but I am concerned about the linear lookup for large enums, but as its in the companion it could call a private non-colliding method on the enum class |
fixes #7227
productPrefix
is now overridden using the enum constant's name and used in the by-name lookup inruntime.EnumValues
.enumLabel
is added as an abstract method toscala.Enum
and implemented using the enum constant's name.productPrefix
is also overridden in concrete enum values to point toenumLabel
, as it is used to implement string lookup of enums.We then also add a default
toString
to an enum value implementation if an override is not provided in the parent classjava based enum values are optimised so that
productPrefix
andenumLabel
willforward to
this.name
in the simple enum case, avoiding an extra field