Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Map's second parameter is Object on reflection for primitive types #4403

Closed
scabug opened this issue Mar 28, 2011 · 3 comments
Closed

Map's second parameter is Object on reflection for primitive types #4403

scabug opened this issue Mar 28, 2011 · 3 comments
Assignees

Comments

@scabug
Copy link

scabug commented Mar 28, 2011

So there I was, trying to reflect on constructor parameters in Scala 2.9.0.RC1.

class Derper(m: Map[String, Long])

class Herper(m: Map[String, Derper])

object DoAReflectThing {
  def main(args: Array[String]) {
    println(classOf[Derper].getConstructors.head.getGenericParameterTypes.head)
    println(classOf[Herper].getConstructors.head.getGenericParameterTypes.head)
  }
}

=== What is the expected behavior? ===

In Scala 2.8.1, the output is this:

scala.collection.immutable.Map<java.lang.String, java.lang.Long>
scala.collection.immutable.Map<java.lang.String, com.yammer.streamie.Derper>

This is awesome, since I have the information I need.

=== What do you see instead? ===

In Scala 2.9.0.RC1, this happens instead:

scala.collection.immutable.Map<java.lang.String, java.lang.Object>
scala.collection.immutable.Map<java.lang.String, com.yammer.streamie.Derper>

sad trombone noise

Now I have no idea what the values of the map should be.

This is really important for me, since I'm the author of Jerkson, a thin Scala layer on top of Jackson. I use reflection to deserialize case classes from JSON objects, but if one of the values of a case class is a Map, I don't have enough information to deserialize it in 2.9.0.RC1.

=== What versions of the following are you using? ===

  • Scala: 2.9.0.RC1
  • Java: 1.6.0_24
  • Operating system: OS X 10.6.7
@scabug
Copy link
Author

scabug commented Mar 28, 2011

Imported From: https://issues.scala-lang.org/browse/SI-4403?orig=1
Reporter: Coda Hale (codahale)
See #4912

@scabug
Copy link
Author

scabug commented Mar 28, 2011

@paulp said:
There isn't much we can do. See #4214 among many others in the 4000s. Putting java.lang.Long there is a lie (there is no method which returns java.lang.Long) and it breaks things. Primitive types can't appear in the signature: that breaks things even worse. There is no choice left but Object.

You can (and will have to) get the information out of the scala signature. Clearly our motivation to make this easy with a scala reflection library has gone way up recently, but it's not imminent. There is code out there somewhere to dredge the info out, and/or you can look at scalap.

@scabug
Copy link
Author

scabug commented May 12, 2012

@retronym said:
I hope the API evolves to make this more convenient (Type#paramss is conspicuously absent from the public API, which is why we have to pattern match below), but reflection will allow for this:

scala> class Derper(m: Map[String, Long])
defined class Derper

scala> val tpe = reflect.mirror.classToType(classOf[Derper])
tpe: reflect.mirror.Type = Derper

scala> val c = tpe.member(reflect.mirror.nme.CONSTRUCTOR)
c: reflect.mirror.Symbol = constructor Derper

scala> val reflect.mirror.MethodType(Seq(param0), _) = c.asType
warning: there were 1 unchecked warnings; re-run with -unchecked for details
param0: reflect.mirror.Symbol = value m

scala> val typeArgs = param0.asType.typeArguments
typeArgs: List[reflect.mirror.Type] = List(String, Long)

scala> typeArgs.last.typeSymbol.fullName
res25: String = scala.Long

So given the replacement, and Paul's explanation of why Java reflection can never again see the full details, let's close as not-a-bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants