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

Compilation failure when using type parameters #31

Closed emchristiansen closed 11 years ago

emchristiansen commented 11 years ago

Please see this StackOverflow post:

http://stackoverflow.com/questions/18725699/scala-pickling-and-type-parameters

This is either a bug or user error. If it is user error, perhaps the documentation should be updated.

heathermiller commented 11 years ago

Firstly, thanks a lot for reporting and cross-linking with SO. We really appreciate it. We're looking into this as we speak.

Note: this ticket is related to (seems like a duplicate?) issue #4

heathermiller commented 11 years ago

It seems that the pickling macro is too restrictive in this case. It fails to actually use the implicit SPickler that's in scope, which it should use. Basically, it just gives up because the type is abstract, and there should be no reason for this.

heathermiller commented 11 years ago

So this is a bug. To resolve this, I think we just need to update the dispatch logic that's generated by the macro. Looking into it now...

heathermiller commented 11 years ago

Fixed in commit 17aac11

With this fix + the use of a "FastTypeTag", all you should have to do is:

def bar[T: SPickler: FastTypeTag](t: T) = t.pickle

So now you can use bar like so:

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

Added these as tests in https://github.com/scala/pickling/blob/2.10.x/core/src/test/scala/pickling/generic-spickler.scala

heathermiller commented 11 years ago

Note: will provide more extensive documentation on this as well :)

emchristiansen commented 11 years ago

That worked for pickling, but unpickling seems still broken. For example, attempting to compile:

def unbar[A: SPickler: FastTypeTag](bytes: Array[Byte]) = 
    BinaryPickle(bytes).unpickle[A]

Results in the error:

[error] /Users/eric/Dropbox/t/2013_q3/pickledb/src/main/scala/PickleDB.scala:21: unpickle needs an explicitly provided type argument
[error]     BinaryPickle(bytes).unpickle[A]
heathermiller commented 11 years ago

Yep, thanks for catching it. A small tweak on our end + a small tweak to what you're trying will do the trick.

Instead of an SPickler, make sure you use an Unpickler on the unpickling side:

def unbar[T: Unpickler: FastTypeTag](s: String) = JSONPickle(s).unpickle[T]

(This is also now in the same test file, https://github.com/scala/pickling/blob/2.10.x/core/src/test/scala/pickling/generic-spickler.scala. It's JSON because what's in the test is JSON, but in the SO article linked to above, you'll see the same example with binary)