-
Notifications
You must be signed in to change notification settings - Fork 79
Force generation to create (un)picklers together #412
Force generation to create (un)picklers together #412
Conversation
* Make `Any` and `Either` to generate pickler/unpickler at the same time. * Improve some documentation by adding more concrete explanations.
Also, it's worth mentioning the fact that we reduce considerably the sourcegen code (by 2/3), which is good for future maintainability of the project. |
3ffb457
to
3347bbd
Compare
I've discovered some issues with this PR, don't merge (yet) please. |
* Macros generate `Pickler[T]`/`Unpickler[T]` together instead of creating them separately. This reduces final code size since now there's only one class instead of two and also improves the reuse of already generated picklers (see issue scala#409). * As now the return type of the implicit method is `AbstractPicklerUnpickler`, there can be some errors because of ambiguous implicit values (e.g. sealed-trait-static) when (un)picklers are explicitly called via `generate`. The fix is to only use `PicklerUnpickler.generate` and deprecate separate explicit creation with `Pickler.generate` and `Unpickler.generate`.
3347bbd
to
7d3a7ac
Compare
* When generating (un)picklers, most of the time we look for the pickler of `Any`. By exposing the pickler of `Any`, we don't manually create one pickler/unpickler every time it's needed. This speeds up the compilation time almost by a factor of 2.
7d3a7ac
to
48e1c4d
Compare
@@ -26,7 +26,8 @@ trait Pickler[T] { | |||
// Shim for Java code. | |||
abstract class AbstractPickler[T] extends Pickler[T] | |||
object Pickler { | |||
def generate[T]: Pickler[T] = macro generator.Compat.genPickler_impl[T] | |||
@deprecated("Use `PicklerUnpickler.generate` instead", "0.11") | |||
def generate[T]: Pickler[T] = macro generator.Compat.genPicklerUnpickler_impl[T] |
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.
yay!
Yeah, the sourgen reduction is nice. I like where we're going. a few notes:
In any case, great work! Really awesome to see all these cleanups!! |
This can already be merged, but there's no way to share/reuse already generated picklers/unpicklers so far and I don't know if it's going to be possible either. Implicits never get out of the scope. The only way to reuse them is this one: implicit val pu = PicklerUnpickler.generate[T] Note the My last commit explains how exposing an |
Agree on having AnyPickler be there by default. I think because we DON'T have contravariant picklers and covariant unpicklers (by necessity) this is fine. Relating to avoiding generating the code, for PicklerUnpickler.generate, the implicit bit is the best we can do. At some point I'd love to be able to have something like: sealed trait Bar
@Autopicklers object Bar
@Autopicklers
final case class Foo.... Where we can autogenerate the |
If you think you're ready on this PR, it's good t merge. Looks good! |
Yes, that's exactly what I thought, the only way Yes, let's merge this, I'll move this conversation to a ticket so that we can make a serious/formal proposal. |
BTW, I was also thinking about that macro annotation. It's a great idea although it changes the design and the API. But we would really get good improvements. Right now, the code size is bloated of unnecessary repetitive picklers/unpicklers. |
Pickler[T]
/Unpickler[T]
together instead ofcreating them separately. This reduces final code size since now
there's only one class instead of two and also improves the reuse of
already generated picklers (see issue Cache already generated picklers for known types #409).
AbstractPicklerUnpickler
, there can be some errors because ofambiguous implicit values (e.g. sealed-trait-static) when (un)picklers
are explicitly called via
generate
. The fix is to only usePicklerUnpickler.generate
and deprecate separate explicit creationwith
Pickler.generate
andUnpickler.generate
.Any
andEither
to generate pickler/unpickler together.