Skip to content
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

[bugfix] Allow calling Pickler.derive on non-mirrored types #3289

Merged
merged 5 commits into from
Nov 2, 2023

Conversation

kciesielski
Copy link
Member

@kciesielski kciesielski commented Oct 31, 2023

Fixes #3287

For custom type T which are not products or coproducts, one should be able to derive a Pickler by providing implicit Reader[T], Writer[T] (or ReadWriter[T]) and Schema[T], then just calling Pickler.derive[T].

Currenlty derive requires a Mirror.Of[T] in its signature, which needs to be removed and moved deeper into a summonFrom resolution, to defer determining how to construct the Pickler.
Additionally, the nonMirrorPickler[T] method will have a better error message, indicating that user should use Pickler.derived[T]

We can't hide nonMirrorPickler entirely, because it has to be in scope for correct resolution of predefined picklers (like String, List, Option, etc).

summonFrom {
case schema: Schema[T] => fromExistingSchemaAndRw[T](schema)
case _ => buildNewPickler[T]()
case _ =>
summonFrom {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't we flatten the summonFroms?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm looks like we can indeed. The code feels strange, but works, thanks :)

case r: Reader[T] => r
case _ =>
errorForType[T](
"Use Pickler.derive[%s] instead of nonMirrorPickler. This method has to be in scope to resolve predefined picklers."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is nonMirrorPickler something people should ever use direclty, or our impl detail?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but it has to be in public scope. Without it Pickler has issues with deriving ReadWriter for String and some other types. This probably may be worked around, but for now I'd keep it public.

// It turns out that summoning a Pickler can sometimes fall into this branch, even if we explicitly state that we want a NotGiven in the method signature
case m: Mirror.Of[T] =>
errorForType[T](
"Found unexpected Mirror. Failed to summon a Pickler[%s]. Try using Pickler.derived or importing sttp.tapir.json.pickler.generic.auto.*"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe suggest reporting a bug in tapir, if this happens?

@adamw adamw merged commit 4eb2647 into master Nov 2, 2023
@mergify mergify bot deleted the 3287-pickler-derive-non-mirrored branch November 2, 2023 09:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Need some advice on using Pickler (java TimeZone)
2 participants