Skip to content

Commit

Permalink
Makes sure unpickling works for scala#31
Browse files Browse the repository at this point in the history
  • Loading branch information
heathermiller committed Sep 11, 2013
1 parent f697054 commit 353f836
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 8 deletions.
21 changes: 14 additions & 7 deletions core/src/main/scala/pickling/Macros.scala
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,6 @@ trait UnpickleMacros extends Macro {
def pickleUnpickle[T: c.WeakTypeTag]: c.Tree = {
import c.universe._
val tpe = weakTypeOf[T]
if (tpe.typeSymbol.asType.isAbstractType) c.abort(c.enclosingPosition, "unpickle needs an explicitly provided type argument")
val pickleArg = c.prefix.tree
q"""
import scala.language.existentials
Expand All @@ -451,8 +450,7 @@ trait UnpickleMacros extends Macro {
import c.universe._
import definitions._
val tpe = weakTypeOf[T]
if (tpe.typeSymbol.asType.isAbstractType) c.abort(c.enclosingPosition, "unpickle needs an explicitly provided type argument")
val sym = tpe.typeSymbol.asClass
val sym = tpe.typeSymbol
val readerArg = c.prefix.tree

def createUnpickler(tpe: Type) = q"implicitly[Unpickler[$tpe]]"
Expand All @@ -466,19 +464,19 @@ trait UnpickleMacros extends Macro {
"""
}

val customDispatch = CaseDef(Ident(nme.WILDCARD), EmptyTree, q"customUnpickler")
val refDispatch = CaseDef(Literal(Constant(FastTypeTag.Ref.key)), EmptyTree, createUnpickler(typeOf[refs.Ref]))

def nonFinalDispatch = {
val compileTimeDispatch = compileTimeDispatchees(tpe) map (subtpe => {
// TODO: do we still want to use something like HasPicklerDispatch (for unpicklers it would be routed throw tpe's companion)?
CaseDef(Literal(Constant(subtpe.key)), EmptyTree, createUnpickler(subtpe))
})
val refDispatch = CaseDef(Literal(Constant(FastTypeTag.Ref.key)), EmptyTree, createUnpickler(typeOf[refs.Ref]))
val runtimeDispatch = CaseDef(Ident(nme.WILDCARD), EmptyTree, q"""
val tag = scala.pickling.FastTypeTag(typeString)
Unpickler.genUnpickler(reader.mirror, tag)
""")

val customDispatch = CaseDef(Ident(nme.WILDCARD), EmptyTree, q"customUnpickler")

q"""
val customUnpickler = implicitly[Unpickler[$tpe]]
if (customUnpickler.isInstanceOf[PicklerUnpicklerNotFound[_]] || customUnpickler.isInstanceOf[Generated]) {
Expand All @@ -489,8 +487,17 @@ trait UnpickleMacros extends Macro {
"""
}

def abstractTypeDispatch =
q"""
val customUnpickler = implicitly[Unpickler[$tpe]]
${Match(q"typeString", List(refDispatch) :+ customDispatch)}
"""

val staticHint = if (sym.isEffectivelyFinal && !isTopLevel) (q"reader.hintStaticallyElidedType()": Tree) else q"";
val dispatchLogic = if (sym.isEffectivelyFinal) finalDispatch else nonFinalDispatch
val dispatchLogic =
if (sym.asType.isAbstractType) abstractTypeDispatch
else if (sym.isEffectivelyFinal) finalDispatch
else nonFinalDispatch
val unpickleeCleanup = if (isTopLevel && shouldBotherAboutCleaning(tpe)) q"clearUnpicklees()" else q""

q"""
Expand Down
6 changes: 5 additions & 1 deletion core/src/test/scala/pickling/generic-spickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,16 @@ class CustomPersonXPickler(implicit val format: PickleFormat) extends SPickler[P
}

class GenericSpickler extends FunSuite {
test("stack-overflow") {
test("stack-overflow-pickle-unpickle") {
def bar[T: SPickler: FastTypeTag](t: T) = t.pickle
def unbar[T: Unpickler: FastTypeTag](s: String) = JSONPickle(s).unpickle[T]

val p = PersonY("Philipp", 32)
assert(bar(p).value == p.pickle.value)
assert(bar(42).unpickle[Int] == 42)

val unbarred = unbar[PersonY](bar(p).value)
assert(unbarred == p)
}

test("issue-4") {
Expand Down

0 comments on commit 353f836

Please sign in to comment.