lloydmeta / enumeratum

A type-safe, reflection-free, powerful enumeration implementation for Scala with exhaustive pattern match warnings and helpful integrations.
MIT License
1.18k stars 146 forks source link

Avoid the use of `toString` for `enumEntry`? #351

Open kubukoz opened 1 year ago

kubukoz commented 1 year ago

Currently enumeratum has this:

trait EnumEntry {

  /** String representation of this Enum Entry.
    *
    * Override in your implementation if needed
    */
  def entryName: String = stableEntryName

  private[this] lazy val stableEntryName: String = toString
}

and it works in normal conditions, but I'd argue that toString should not be relied upon. entryName can affect serialization and toString is pretty arbitrary - we made this assumption in better-tostring, and it turns out to be incompatible with enumeratum. We have a workaround, but it's pretty inconvenient.

What do you think about the possibility of doing something else? i.e. getting the entry name based on the actual source names of the enum members (derived at compile time).

lloydmeta commented 1 year ago

entryName could be overridden though so that the (private) call to toString doesn’t get used; is that not sufficient?

kubukoz commented 1 year ago

It works, but it's pretty manual (one has to change the base trait of all their enums). Ideally it wouldn't require source-level changes.

snilard commented 1 year ago

I would also vote for some kind of refactor that the enumEntry is not using toString. Using macro to evolve it from class name at compile time looks as very logical Scala way of doing that. Or even using getClass().getName() at runtime looks as better option than toString.

This simple thing can break Enumeratum completelly:

sealed trait MyEnum extends EnumEntry with Snakecase {
  override def toString(): String = "string"
}
kubukoz commented 1 year ago

@snilard getClass probably runs into problems on Scala.js / Scala Native, both of which are supported by enumeratum.

I'd vote for macros.