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

Custom type serialization with bimap() error #124

Open
4 tasks done
martin-ockajak opened this issue Feb 5, 2024 · 1 comment
Open
4 tasks done

Custom type serialization with bimap() error #124

martin-ockajak opened this issue Feb 5, 2024 · 1 comment
Labels
bug Something isn't working

Comments

@martin-ockajak
Copy link

martin-ockajak commented Feb 5, 2024

Task List

  • Steps to reproduce provided
  • Stacktrace (if present) provided
  • Example that reproduces the problem uploaded to Github
  • Full description of the issue provided (see below)

Commit or Tag Version

v1.9.1

Expected Behaviour

Serializing a value of custom type using an implicit FromTo instance created with bimap() should work.

Note: The equivalent code for uPickle works as expected.

Actual Behaviour

The following error occurs using weePickle 1.9.1 with Scala 2.13.12:

Exception in thread "main" java.lang.ClassCastException: class com.rallyhealth.weepickle.v1.core.Types$To$Delegate
cannot be cast to class com.rallyhealth.weepickle.v1.core.Types$Tagged 
(com.rallyhealth.weepickle.v1.core.Types$To$Delegate and com.rallyhealth.weepickle.v1.core.Types$Tagged are in unnamed module of loader 'app')
        at com.rallyhealth.weepickle.v1.core.Types.com$rallyhealth$weepickle$v1$core$Types$$findTagName(Types.scala:133)
        at com.rallyhealth.weepickle.v1.core.Types$TaggedTo$Node.<init>(Types.scala:286)
        at com.rallyhealth.weepickle.v1.core.Types$To$.merge(Types.scala:97)
        at stdin$.delayedEndpoint$stdin$1(stdin:9)
        at stdin$delayedInit$body.apply(stdin:65534)
        at scala.Function0.apply$mcV$sp(Function0.scala:42)
        at scala.Function0.apply$mcV$sp$(Function0.scala:42)
        at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:17)
        at scala.App.$anonfun$main$1(App.scala:98)
        at scala.App.$anonfun$main$1$adapted(App.scala:98)
        at scala.collection.IterableOnceOps.foreach(IterableOnce.scala:576)
        at scala.collection.IterableOnceOps.foreach$(IterableOnce.scala:574)
        at scala.collection.AbstractIterable.foreach(Iterable.scala:933)
        at scala.App.main(App.scala:98)
        at scala.App.main$(App.scala:96)
        at stdin$.main(stdin:65534)
        at stdin.main(stdin)

Steps to Reproduce

Paste this snippet into a shell (requires Scala CLI):

scala-cli run - << END

//> using scala 2.13.12
//> using dep com.rallyhealth::weepickle-v1:1.9.1
import com.rallyhealth.weejson.v1.{Str, Value}
import com.rallyhealth.weepickle.v1.WeePickle.{FromScala, FromTo, macroFromTo}

class Custom(a: String)

implicit val fromTo: FromTo[Custom] = macroFromTo[Value].bimap[Custom](
  _ => Str(""),
  _ => new Custom(""),
)

FromScala(Custom(""))

END

Related Code

import com.rallyhealth.weejson.v1.{Str, Value}
import com.rallyhealth.weepickle.v1.WeePickle.{FromScala, FromTo, macroFromTo}
class Custom(a: String)

implicit val fromTo: FromTo[Custom] = macroFromTo[Value].bimap[Custom](
  _ => Str(""),
  _ => new Custom(""),
)

FromScala(Custom(""))

Further comments

The type cast error is caused by this function in Types.scala:

    def merge[T](rws: FromTo[_ <: T]*): TaggedFromTo[T] = {
      new TaggedFromTo.Node(rws.asInstanceOf[Seq[TaggedFromTo[T]]]: _*)
    }

The function assumes that will always recieve a sequence of TaggedFromTo but this is apparently not guaranteed.

This function seems to be invoked by this part of the FromTo derivation macro in MacroImplicits.scala:

    override def mergeTrait(subtrees: Seq[Tree], subtypes: Seq[Type], targetType: Type): Tree = {
      q"${c.prefix}.To.merge[$targetType](..$subtrees)"
    }
@martin-ockajak martin-ockajak added the bug Something isn't working label Feb 5, 2024
@martin-ockajak martin-ockajak changed the title Custom type serialization with bimap error Custom type serialization with bimap() error Feb 5, 2024
@rremple
Copy link

rremple commented Mar 6, 2024

The issue here is that Value is a sealed trait, but does not declare the discriminator that macroFromTo requires of sealed traits. However, you shouldn't need it -- Value is already defined as its own visitor, and FromValue and ToValue are already defined by default. If, instead of using macroFromTo[Value] here, you used fromTo[Value] (which will implicitly join the implicit FromValue and ToValue definitions as a FromTo), then everything should work as expected. (And it should compile a tiny bit faster, since no macro is required.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants