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

Use a `NotGiven` implicit to avoid infinite loops caused by superTypeWriter/superTypeReader #471

Closed lihaoyi closed 1 year ago

lihaoyi commented 1 year ago

Fixes https://github.com/com-lihaoyi/upickle/issues/468

The basic problem is that with enum A: case B, Calling implicit def rw: RW[A] = macroR will end up looking for a R[B], which will trigger superTypeReader[B, A], which picks up the rw we are defining and becoming an infinite recursion/loop.

The fix here is to ensure that when calling macroR[T]/macroW[T]/macroRW[T], that superTypeReader and superTypeWriter do not trigger on type [_, T]. We can do that by requiring that they take a NotGiven[CurrentlyDeriving[T]], and providing an implicit CurrentlyDeriving[T] in the macroR/macroW/macroRW bodies.

Added some compileError tests to ensure these raise implicit not found errors as expected

While superTypeWriter/superTypeReader had their signatures changed, the fact that they are inline means there are no binary compatibility concerns

This is only necessary for Scala 3, since Scala 2 doesn't have superTypeWriter/superTypeReader in the first place due to diverging implicit issues (see https://github.com/com-lihaoyi/upickle/pull/459)