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

Unable to deserialize Option[X] member of case class. #50

Closed yashton closed 11 years ago

yashton commented 11 years ago

This is the minimum test necessary to reproduce. I have a more complicated case class than this in my code base, but the Option[X] member appears to be the problem. The October 13th snapshot update seems to have introduced the bug. I get the same error when in 2.10.3-RC2 as well as 2.10.2.

import scala.pickling._
import scala.pickling.binary._

object Test {
  case class TestA (x: Option[Int])
  TestA(Some(1)).pickle.unpickle[TestA]

  case class TestB (x: Option[String])
  TestB(Some("hello")).pickle.unpickle[TestB]
}

I turned on -Xlog-implicits to get the following error on compile

...
[info] /Users/ashton/Projects/event_api/src/main/scala/Pickling.scala:7: pickling.this.Unpickler.genUnpickler is not a valid implicit value for scala.pickling.Unpickler[Test.TestA] because:
[info] hasMatchingSymbol reported error: value forcefulSet is not a member of reflect.runtime.universe.FieldMirror
[info]   TestA(Some(1)).pickle.unpickle[TestA]
[info]                                 ^
[error] /Users/ashton/Projects/event_api/src/main/scala/Pickling.scala:7: Cannot generate an unpickler for Test.TestA. Recompile with -Xlog-implicits for details
[error]   TestA(Some(1)).pickle.unpickle[TestA]
[error]
...

I was able to find the FieldMirror class in the nightly docs http://www.scala-lang.org/files/archive/nightly/docs-2.10.2/library/index.html#scala.reflect.api.Mirrors$FieldMirror

forcefulSet does not appear to be a member, but it does appear to be added with RichFieldMirror implicit in core/src/main/scala/pickling/internal/package.scala

The following does work

scala> val x:Option[Int] = Some(1)
x: Option[Int] = Some(1)

scala> val y = x.pickle
y: scala.pickling.binary.BinaryPickle = BinaryPickle([0,0,0,21,115,99,97,108,97,46,83,111,109,101,91,115,99,97,108,97,46,73,110,116,93,0,0,0,1])

scala> y.unpickle[Option[Int]]
res18: Option[Int] = Some(1)
heathermiller commented 11 years ago

Thanks for reporting. Looking into it :)

JonyEpsilon commented 11 years ago

I see the same with this code:

case class TestCase(p: Option[String])

object Test extends App {

  import scala.pickling._
  import json._

  val m = TestCase(Some("a"))
  val pckl = m.pickle
  val lst = pckl.unpickle[TestCase]

}

Improbably long string of error messages generated:

Last login: Mon Oct 14 01:21:33 on ttys002
pickle git:master jony$ sbt
[info] Set current project to sbt-pickling-example (in build file:/Users/jony/Desktop/pickle/)
> compile
[info] Updating {file:/Users/jony/Desktop/pickle/}pickle...
[warn] Binary version (0.8.0-SNAPSHOT) for dependency org.scala-lang#scala-pickling_2.10;0.8.0-SNAPSHOT
[warn]  in sbt-pickling-example#sbt-pickling-example_2.10;0.1-SNAPSHOT differs from Scala binary version in project (2.10).
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Compiling 1 Scala source to /Users/jony/Desktop/pickle/target/scala-2.10/classes...
[info] /Users/jony/Desktop/pickle/Test.scala:9: pickling.this.SPickler.genPickler is not a valid implicit value for scala.pickling.SPickler[TestCase] because:
[info] stepping aside: repeating itself
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: pickling.this.SPickler.genPickler is not a valid implicit value for scala.pickling.SPickler[Option[String]] because:
[info] stepping aside: repeating itself
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: pickling.this.SPickler.genPickler is not a valid implicit value for scala.pickling.SPickler[Null] because:
[info] stepping aside: repeating itself
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: pickling.this.SPickler.genPickler is not a valid implicit value for scala.pickling.SPickler[Null] because:
[info] stepping aside: there are other candidates
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: materializing requested reflect.runtime.universe.type.TypeTag[None.type] using `package`.this.materializeTypeTag[None.type](scala.reflect.runtime.`package`.universe)
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: pickling.this.SPickler.genPickler is not a valid implicit value for scala.pickling.SPickler[None.type] because:
[info] stepping aside: repeating itself
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: materializing requested reflect.runtime.universe.type.TypeTag[Some[String]] using `package`.this.materializeTypeTag[Some[String]](scala.reflect.runtime.`package`.universe)
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: pickling.this.SPickler.genPickler is not a valid implicit value for scala.pickling.SPickler[Some[String]] because:
[info] stepping aside: repeating itself
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: materializing requested reflect.runtime.universe.type.TypeTag[String] using `package`.this.materializeTypeTag[String](scala.reflect.runtime.`package`.universe)
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: pickling.this.SPickler.genPickler is not a valid implicit value for scala.pickling.SPickler[String] because:
[info] stepping aside: repeating itself
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: pickling.this.SPickler.genPickler is not a valid implicit value for scala.pickling.SPickler[String] because:
[info] stepping aside: there are other candidates
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: materializing requested reflect.runtime.universe.type.TypeTag[Null] using `package`.this.materializeTypeTag[Null](scala.reflect.runtime.`package`.universe)
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: materializing requested reflect.runtime.universe.type.TypeTag[Option[String]] using `package`.this.materializeTypeTag[Option[String]](scala.reflect.runtime.`package`.universe)
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: materializing requested reflect.runtime.universe.type.TypeTag[Null] using `package`.this.materializeTypeTag[Null](scala.reflect.runtime.`package`.universe)
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: pickling.this.SPickler.genPickler is not a valid implicit value for scala.pickling.SPickler[Null] because:
[info] stepping aside: repeating itself
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: pickling.this.SPickler.genPickler is not a valid implicit value for scala.pickling.SPickler[Null] because:
[info] stepping aside: there are other candidates
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: materializing requested reflect.runtime.universe.type.TypeTag[TestCase] using `package`.this.materializeTypeTag[TestCase](scala.reflect.runtime.`package`.universe)
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: pickling.this.SPickler.genPickler is not a valid implicit value for scala.pickling.SPickler[TestCase] because:
[info] stepping aside: repeating itself
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: pickling.this.SPickler.genPickler is not a valid implicit value for scala.pickling.SPickler[Option[String]] because:
[info] stepping aside: repeating itself
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: materializing requested reflect.runtime.universe.type.TypeTag[Null] using `package`.this.materializeTypeTag[Null](scala.reflect.runtime.`package`.universe)
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: materializing requested reflect.runtime.universe.type.TypeTag[None.type] using `package`.this.materializeTypeTag[None.type](scala.reflect.runtime.`package`.universe)
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: pickling.this.SPickler.genPickler is not a valid implicit value for scala.pickling.SPickler[None.type] because:
[info] stepping aside: repeating itself
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: materializing requested reflect.runtime.universe.type.TypeTag[Some[String]] using `package`.this.materializeTypeTag[Some[String]](scala.reflect.runtime.`package`.universe)
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: pickling.this.SPickler.genPickler is not a valid implicit value for scala.pickling.SPickler[Some[String]] because:
[info] stepping aside: repeating itself
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: materializing requested reflect.runtime.universe.type.TypeTag[String] using `package`.this.materializeTypeTag[String](scala.reflect.runtime.`package`.universe)
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: pickling.this.SPickler.genPickler is not a valid implicit value for scala.pickling.SPickler[String] because:
[info] stepping aside: repeating itself
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: pickling.this.SPickler.genPickler is not a valid implicit value for scala.pickling.SPickler[String] because:
[info] stepping aside: there are other candidates
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: materializing requested reflect.runtime.universe.type.TypeTag[Null] using `package`.this.materializeTypeTag[Null](scala.reflect.runtime.`package`.universe)
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: materializing requested reflect.runtime.universe.type.TypeTag[Option[String]] using `package`.this.materializeTypeTag[Option[String]](scala.reflect.runtime.`package`.universe)
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:9: materializing requested reflect.runtime.universe.type.TypeTag[TestCase] using `package`.this.materializeTypeTag[TestCase](scala.reflect.runtime.`package`.universe)
[info]   val pckl = m.pickle
[info]                ^
[info] /Users/jony/Desktop/pickle/Test.scala:10: materializing requested reflect.runtime.universe.type.TypeTag[TestCase] using `package`.this.materializeTypeTag[TestCase](scala.reflect.runtime.`package`.universe)
[info]   val lst = pckl.unpickle[TestCase]
[info]                          ^
[info] /Users/jony/Desktop/pickle/Test.scala:10: pickling.this.Unpickler.genUnpickler is not a valid implicit value for scala.pickling.Unpickler[TestCase] because:
[info] stepping aside: repeating itself
[info]   val lst = pckl.unpickle[TestCase]
[info]                          ^
[info] /Users/jony/Desktop/pickle/Test.scala:10: materializing requested scala.reflect.type.ClassTag[TestCase] using `package`.this.materializeClassTag[TestCase]()
[info]   val lst = pckl.unpickle[TestCase]
[info]                          ^
[info] /Users/jony/Desktop/pickle/Test.scala:10: materializing requested reflect.runtime.universe.type.TypeTag[TestCase] using `package`.this.materializeTypeTag[TestCase](scala.reflect.runtime.`package`.universe)
[info]   val lst = pckl.unpickle[TestCase]
[info]                          ^
[info] /Users/jony/Desktop/pickle/Test.scala:10: pickling.this.Unpickler.genUnpickler is not a valid implicit value for scala.pickling.Unpickler[TestCase] because:
[info] hasMatchingSymbol reported error: value forcefulSet is not a member of reflect.runtime.universe.FieldMirror
[info]   val lst = pckl.unpickle[TestCase]
[info]                          ^
[error] /Users/jony/Desktop/pickle/Test.scala:10: Cannot generate an unpickler for TestCase. Recompile with -Xlog-implicits for details
[error]   val lst = pckl.unpickle[TestCase]
[error]                          ^
[info] /Users/jony/Desktop/pickle/Test.scala:10: pickling.this.Unpickler.genUnpickler is not a valid implicit value for scala.pickling.Unpickler[TestCase] because:
[info] stepping aside: repeating itself
[info]   val lst = pckl.unpickle[TestCase]
[info]                          ^
[info] /Users/jony/Desktop/pickle/Test.scala:10: materializing requested scala.reflect.type.ClassTag[TestCase] using `package`.this.materializeClassTag[TestCase]()
[info]   val lst = pckl.unpickle[TestCase]
[info]                          ^
[info] /Users/jony/Desktop/pickle/Test.scala:10: materializing requested reflect.runtime.universe.type.TypeTag[TestCase] using `package`.this.materializeTypeTag[TestCase](scala.reflect.runtime.`package`.universe)
[info]   val lst = pckl.unpickle[TestCase]
[info]                          ^
[info] /Users/jony/Desktop/pickle/Test.scala:10: pickling.this.Unpickler.genUnpickler is not a valid implicit value for scala.pickling.Unpickler[TestCase] because:
[info] hasMatchingSymbol reported error: value forcefulSet is not a member of reflect.runtime.universe.FieldMirror
[info]   val lst = pckl.unpickle[TestCase]
[info]                          ^
[error] one error found
[error] (compile:compile) Compilation failed
[error] Total time: 7 s, completed 16-Oct-2013 21:14:43
>
phaller commented 11 years ago

Fixed in https://github.com/scala/pickling/pull/54

JonyEpsilon commented 11 years ago

Just to confirm that that works for me. Thanks.