amnaredo / test

0 stars 0 forks source link

Case companion object in sealed hierarchy not supported #243

Open amnaredo opened 3 years ago

amnaredo commented 3 years ago

The following compiles but fails at runtime:

import upickle.default._

sealed trait Data

case class Data1(i: Int, s: String) extends Data
case object Data1 extends Data

implicit val rw: ReadWriter[Data] = ReadWriter.merge(macroRW[Data1], macroRW[Data1.type])

read[Data](write[Data](Data1(1, "x"))) // res0: Data = Data1(1,x)
read[Data](write[Data](Data1))         // upickle.core.AbortException: missing keys in dictionary: i, s at index 46

Switching the order of the instances in merge returns incorrect result.

import upickle.default._

sealed trait Data

case class Data1(i: Int, s: String) extends Data
case object Data1 extends Data

implicit val rw: ReadWriter[Data] = ReadWriter.merge(macroRW[Data1.type], macroRW[Data1])

read[Data](write[Data](Data1(1, "x"))) // res0: Data = Data1, incorrect
read[Data](write[Data](Data1))         // res1: Data = Data1

ID: 257 Original Author: ajaychandran

amnaredo commented 3 years ago

I think I'm going to call this a wontfix; we can't really change this without changing the way parsers deal with singletons/companions, and even if we were willing to make the change it would mean appending a $ or similar to companion object's $type tag which is pretty ugly in the common case.

A workaround for now could be to use the @upickle.implicits.key annotation to specify a different $type tag manually:

@ {
  import upickle.default._

  sealed trait Data

  case class Data1(i: Int, s: String) extends Data
  @upickle.implicits.key("Data1Companion")
  case object Data1 extends Data

  implicit val rw: ReadWriter[Data] = ReadWriter.merge(macroRW[Data1], macroRW[Data1.type])

  read[Data](write[Data](Data1(1, "x"))) // res0: Data = Data1(1,x)
  read[Data](write[Data](Data1))
  }
import upickle.default._

defined trait Data
defined class Data1
defined object Data1
rw: ReadWriter[Data] = upickle.core.Types$TaggedReadWriter$Node@42401b81
res1_5: Data = Data1(1, "x")
res1_6: Data = Data1

Original Author: lihaoyi