com-lihaoyi / upickle

uPickle: a simple, fast, dependency-free JSON & Binary (MessagePack) serialization library for Scala
https://com-lihaoyi.github.io/upickle
MIT License
715 stars 164 forks source link

Normalize handling of Scala 3 enums, remove allocations from reader #445

Closed lihaoyi closed 1 year ago

lihaoyi commented 1 year ago

Fixes #356

The Scala 3 code for handling enums was a parallel code path from that handling sealed hierarchies: going through separate EnumReader/EnumWriters, raising separate error messages, and not supporting common use cases. This PR makes Scala 3 enums use the same sealed-trait-handling logic as far as possible, allowing them to support things like parametrized enums and parametrized enum cases. This also reduces the complexity of the code by ensuring both enums and sealed traits go through a common code path, and should help avoid accidental divergence in future

One notable point of divergence is the choice of type tag. Enums use the short name of the type Foo, whereas sealed traits use the fully qualified name pkg.name.Foo. For now, I leave both behaviors in place, though ideally we should unify them at some point

I also took the opportunity to tweak the Scala 3 Reader.scala macros, to move more logic to compile time to better mirror that behavior in Scala 2. This replaces a runtime Map in each case class reader with a macro-generated match statement, and reduces the number of runtime Arrays we need to allocate (though does not quite eliminate all of them, we still have two arrays for params and visitors)

All existing tests pass, and added new tests to verify the newly-working functionality.

I'll leave this up for a few days in case anyone wants to review it