0

This script uses reflection to find the type signature of a constructor. It contains the same code inside an object and at the top level:

// Scala 2.11.1
case class Dirigible(cubicFeet: Int)

object Object {
  val u = scala.reflect.runtime.universe
  val ctor = u.weakTypeOf[Dirigible].decl(u.termNames.CONSTRUCTOR).typeSignature
  def run() {
    println(ctor)
  }
}

Object.run()

val u = scala.reflect.runtime.universe
val ctor = u.weakTypeOf[Dirigible].decl(u.termNames.CONSTRUCTOR).typeSignature
println(ctor)

Here is the output:

(cubicFeet: Int)$anon.this.Dirigible
<notype>

Why does the top-level code fail while the code inside Object works?

The same failure occurs if I put the println inside a top-level def and call it from the top level.

The top-level code works if I run the file in the REPL via scala -i refltest.scala. That's to be expected, since the REPL puts everything into an object. What I don't understand is, why does code's being inside an object affect the results of reflection?

Ben Kovitz
  • 4,920
  • 1
  • 22
  • 50

1 Answers1

1

The script runner wraps your code in a local anonymous class; your code is run as part of the initializer.

I don't know why that breaks reflection, but it's a duplicate of this question from a couple of years ago. That was edited to say the problem was fixed, but I don't see it working.

As a workaround, wrap your code in a block:

locally {
val u = scala.reflect.runtime.universe
val ctor = u.weakTypeOf[Dirigible].decl(u.termNames.CONSTRUCTOR).typeSignature
println(ctor)
}

Maybe it has to do with init order and how the local class is compiled.

Community
  • 1
  • 1
som-snytt
  • 39,429
  • 2
  • 47
  • 129
  • @eugene-burmako might be interested. – som-snytt May 24 '14 at 12:06
  • Thanks. I just tried that and it works. And thanks for showing me `locally`: I hadn't heard of that before. – Ben Kovitz May 24 '14 at 13:52
  • @EugeneBurmako's answer [to this question](http://stackoverflow.com/questions/23828246/macro-implementation-reference-has-wrong-shape-in-the-scala-documentation-exam?lq=1) leads me to wonder if the problem is that `u` is not a static object. Indeed, when I replace each reference to `u` with `scala.reflect.runtime.universe`, it works. Still a little baffling, though, since `u` refers to the same `universe` object, which presumably is static. – Ben Kovitz May 24 '14 at 14:49
  • Yes, I was going to post the -Xprint output, too. Here, it's not the u value but maybe the "stable path" it's inspecting. – som-snytt May 24 '14 at 14:58
  • @BenKovitz What if you do `val u: scala.reflect.runtime.universe.type = scala.reflect.runtime.universe`? – Eugene Burmako May 26 '14 at 07:24
  • @EugeneBurmako Same result: ``. – Ben Kovitz May 26 '14 at 07:52