scala / pickling

Fast, customizable, boilerplate-free pickling support for Scala
lampwww.epfl.ch/~hmiller/pickling
BSD 3-Clause "New" or "Revised" License
831 stars 79 forks source link

`Pickling` fails to generate automatically picklers/unpicklers [SOLVED] #389

Open jvican opened 8 years ago

jvican commented 8 years ago

I'm using scala-pickling in a project and I've noticed that sometimes minor changes in the codebase can lead to unexpected errors when generating picklers/unpicklers. For instance, changing names of folders/packages. Why? Probably because that triggers changes in the compilation order of the program.

When this error happens, run set scalacOptions += "-Xlog-implicits" in sbt and browse through the immense log that just appeared in front of you. There will be an exception from the macro because it couldn't find the subclasses of the entity that you want to pickle. Something like:

[info] java.lang.Exception: Didn't find any concrete subtypes of abstract fp.model.ClientRequest, this may mean you need to use the @directSubclasses annotation to manually tell the compiler about subtypes
[info]  at scala.pickling.Macro.compileTimeDispatcheesNotEmpty(Tools.scala:345)
[info]  at scala.pickling.UnpickleMacros$class.createCompileTimeDispatch(Macros.scala:777)
[info]  at scala.pickling.Compat$$anon$4.createCompileTimeDispatch(Compat.scala:25)
[info]  at scala.pickling.UnpicklerMacros$class.unpickleLogic(Macros.scala:606)
[info]  at scala.pickling.Compat$$anon$4.unpickleLogic(Compat.scala:25)
[info]  at scala.pickling.UnpicklerMacros$$anonfun$impl$4.apply(Macros.scala:668)
[info]  at scala.pickling.UnpicklerMacros$$anonfun$impl$4.apply(Macros.scala:661)
[info]  at scala.pickling.Macro.preferringAlternativeImplicits(Tools.scala:401)
[info]  at scala.pickling.UnpicklerMacros$class.impl(Macros.scala:661)
[info]  at scala.pickling.Compat$$anon$4.impl(Compat.scala:25)
[info]  at scala.pickling.Compat$.UnpicklerMacros_impl(Compat.scala:26)
[info]       val msg = BinaryPickle(arr).unpickle[Message]

SOLUTION: use @directSubclasses(Array(classOf[Subclass1], classOf[Subclass2], ... )) where Subclass1 and Subclass2 are the subclasses of the entity to be pickled. Beware that this is not necessary for objects (mostly because there is no way to get a class of an object at compile-time). If you have a type constructor (let's say it's MyList[T]), use classOf[MyList[_]].

Kudos to @phaller for helping me spot the error.

jvican commented 8 years ago

Could anyone label this as documentation? Thanks.