I'm trying to get a basic upickle example to work and it seems I'm missing something here. I want to try out the example provided on the readme page for upickle
import upickle._
sealed trait A
@key("Bee") case class B(i: Int) extends A
case object C extends A
Then, my code is:
object Model {
def main(args: Array[String]): Unit = {
val a = B(5): A
println(a)
val out = write(a)
println(out)
val a2 = read[A](out)
println(a2)
println(a == a2)
}
}
All I get is the error:
The referenced trait [[A]] does not have any sub-classes. This may happen due to a limitation of scalac (SI-7046) given that the trait is not in the same package. If this is the case, the hierarchy may be defined using integer constants.
I have two questions:
Ever had the syndrome that you can spend multiple hours on a problem like this, and you solve it minutes after asking the StackOverflow question?
It turns out that due to compiler-specific details, such a sealed trait won't know its direct subclasses until after the point in the file where it's defined. So, in this case, I had defined the trait and its cases after the main method, where upickle would do its macro expansion and magic. At this point, it won't know about the trait's cases. If the main method is moved in the same file after the definition of the trait and its cases, it will work.
I encountered this error in a Scala.js project where I shared a sealed abstract class between server and client.
The solution was to use the Typelevel compiler instead of the default Lightbend one.
This is easily done:
build.properties
: sbt.version=0.13.13-M1
build.sbt
: scalaOrganization in ThisBuild:= "org.typelevel"
For completeness' sake, this is the class I can now share between client and server:
sealed abstract class ServerResponse
case class Ok(msg: String) extends ServerResponse
case class Failure(msg: String) extends ServerResponse
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With