scala - Context bound [T: Manifest] -> Nothing -


i use jackson scala module.

i've created little serialization tool handle json payloads received play2 framework.

  def unserializepayloadas[t](implicit requestcontext: requestcontext[jsvalue]): t = {     val json: string = json.stringify(requestcontext.request.body)     unserialize(json)   }    def unserialize[t](json: string): t = {     objectmapper.readvalue(json)   } 

the readvalue of jackson scala module has signature:

  def readvalue[t: manifest](content: string): t = {     readvalue(content, constructtype[t])   } 

when trying use deserialization code, have stack.

caused by: com.fasterxml.jackson.databind.jsonmappingexception: can not instantiate abstract type [simple type, class scala.runtime.nothing$] (need add/enable type information?) @ [source: java.io.stringreader@7bb78579; line: 1, column: 2] @ com.fasterxml.jackson.databind.jsonmappingexception.from(jsonmappingexception.java:164) ~[jackson-databind-2.2.0.jar:2.2.0] @ com.fasterxml.jackson.databind.deser.std.throwabledeserializer.deserializefromobject(throwabledeserializer.java:77) ~[jackson-databind-2.2.0.jar:2.2.0] @ com.fasterxml.jackson.databind.deser.beandeserializer.deserialize(beandeserializer.java:121) ~[jackson-databind-2.2.0.jar:2.2.0] @ com.fasterxml.jackson.databind.objectmapper._readmapandclose(objectmapper.java:2888) ~[jackson-databind-2.2.0.jar:2.2.0] @ com.fasterxml.jackson.databind.objectmapper.readvalue(objectmapper.java:2041) ~[jackson-databind-2.2.0.jar:2.2.0] @ com.fasterxml.jackson.module.scala.experimental.scalaobjectmapper$class.readvalue(scalaobjectmapper.scala:157) ~[jackson-module-scala_2.10-2.2.0.jar:2.2.0] @ utils.customserializer$$anon$1.readvalue(customserializer.scala:17) ~[na:na] @ utils.customserializer$.unserialize(customserializer.scala:39) ~[na:na] @ utils.customserializer$.unserializepayloadas(customserializer.scala:35) ~[na:na] 

as expected, works fine when add manifest in code:

  def unserializepayloadas[t: manifest](implicit requestcontext: requestcontext[jsvalue]): t = {     val json: string = json.stringify(requestcontext.request.body)     unserialize(json)   }    def unserialize[t: manifest](json: string): t = {     objectmapper.readvalue(json)   } 

can explain happens there? when call method manifest context bound, parametrized method no manifest, manifest of nothing provided first method?

i have expected kind of compilation error, telling me i'm calling readvalue parametrized type has no manifest or that, seems more fail-fast.

take simpler example:

def getmanifest[a: manifest] = implicitly[manifest[a]] 

or equivalent desugared version:

def getmanifest[a](implicit whatever: manifest[a]) = whatever 

and then:

scala> def getit[t]: manifest[t] = getmanifest <console>:8: error: type mismatch;  found   : manifest[nothing]  required: manifest[t] note: nothing <: t, trait manifest invariant in type t. may wish investigate wildcard type such `_ <: t`. (sls 3.2.10)        def getit[t]: manifest[t] = getmanifest                                    ^ 

what's happening when compiler tries infer type parameter getmanifest, there lots of types have manifest instances in scope, , has no way choose between them, goes default choice, nothing.

(you're seeing error @ runtime instead of compile-time because, well, that's happens when use reflection-based approaches serialization.)

we can add context bound:

def getit[t: manifest]: manifest[t] = getmanifest 

or, equivalently:

def getit[t](implicit whatever: manifest[t]): manifest[t] = getmanifest 

now fine—there's single precise manifest instance in scope, compiler can (appropriately) resolve type parameter getmanifest t.

you can see little more dramatically in following example:

scala> trait foo[a] defined trait foo  scala> def getfoo[a: foo] = implicitly[foo[a]] getfoo: [a](implicit evidence$1: foo[a])foo[a]  scala> implicit object stringfoo extends foo[string] defined module stringfoo  scala> def getit[t]: foo[t] = getfoo <console>:10: error: type mismatch;  found   : foo[string]  required: foo[t]        def getit[t]: foo[t] = getfoo                               ^ 

since there's 1 foo instance in scope (for string), compiler can pick when it's resolving type parameter getfoo, , end different type mismatch.


Comments