Reflection on package object crashes the first time, works after?

179 views
Skip to first unread message

Haoyi Li

unread,
Feb 25, 2015, 12:39:20 AM2/25/15
to scala-internals
// build.sbt
scalaVersion := "2.11.5"

libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value % "provided"

// Main.scala
package ammonite
package object ops {
  object RegexContext
  object ls
  implicit class RegexContext(sc: StringContext)
}

object Main {
  def main(args: Array[String]): Unit = {
    def typeOf[T: scala.reflect.runtime.universe.WeakTypeTag](t: => T) =
      scala.reflect.runtime.universe.weakTypeOf[T]
//    util.Try(typeOf(ammonite.ops.ls))
    typeOf(ammonite.ops.ls)
    typeOf(ammonite.ops.ls)
  }
}

This crashes with java.lang.AssertionError: assertion failed: pkgClass = package ops, sym = method RegexContext, existing = object RegexContext (depth=0)
java.lang.AssertionError: assertion failed: pkgClass = package ops, sym = method RegexContext, existing = object RegexContext (depth=0):

Commenting out the util.Try makes it not crash

// Main.scala
package ammonite
package object ops {
  object RegexContext
  object ls
  implicit class RegexContext(sc: StringContext)
}

object Main {
  def main(args: Array[String]): Unit = {
    def typeOf[T: scala.reflect.runtime.universe.WeakTypeTag](t: => T) =
      scala.reflect.runtime.universe.weakTypeOf[T]
    util.Try(typeOf(ammonite.ops.ls))
    typeOf(ammonite.ops.ls)
    typeOf(ammonite.ops.ls)
  }
}

If I put ls last, it crashes regardless of the Try with scala.ScalaReflectionException: object ammonite.ops.ls not found.

// Main.scala
package ammonite
package object ops {
  object RegexContext
  implicit class RegexContext(sc: StringContext)
  object ls
}

object Main {
  def main(args: Array[String]): Unit = {
    def typeOf[T: scala.reflect.runtime.universe.WeakTypeTag](t: => T) =
      scala.reflect.runtime.universe.weakTypeOf[T]
    util.Try(typeOf(ammonite.ops.ls))
    typeOf(ammonite.ops.ls)
    typeOf(ammonite.ops.ls)
  }
}

Is this a bug?

Jason Zaugg

unread,
Feb 25, 2015, 1:21:10 AM2/25/15
to scala-i...@googlegroups.com
On Wed, Feb 25, 2015 at 3:38 PM, Haoyi Li <haoy...@gmail.com> wrote:

Is this a bug?

Yep, it is a bug. Lodged as SI-9182

Here's a further minimization:
package object ops {
  object A
  def A(a: Any) = ()
}

object Main {
  def main(args: Array[String]): Unit
 = {
    val pack = scala.reflect.runtime.currentMirror.staticModule("ops.package")
    println(pack.info.decls.toList.map(_.toString).sorted.mkString("\n"))
  }
}

The fix simply involves toning down the over-eager assertion, which incorrectly assumes that modules and methods can’t be overloaded in a package scope.

-jason

Som Snytt

unread,
Feb 25, 2015, 1:22:53 AM2/25/15
to scala-internals

The comment says,

// materializing multiple copies of the same symbol in PackageScope is a very popular bug

but I don't it meant this one.

--
You received this message because you are subscribed to the Google Groups "scala-internals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-interna...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Haoyi Li

unread,
Feb 25, 2015, 4:41:18 AM2/25/15
to scala-internals
Cool, thanks! I guess that last error is a consequence of the first one then?

Jason Zaugg

unread,
Feb 26, 2015, 12:45:27 AM2/26/15
to scala-i...@googlegroups.com
On Wed, Feb 25, 2015 at 7:40 PM, Haoyi Li <haoy...@gmail.com> wrote:
Cool, thanks! I guess that last error is a consequence of the first one then?

Yep. I just verified that my patch makes that example work:
% qscalac sandbox/test.scala && qscala ammonite.Main
(remotes/retronym/ticket/9182) /code/scala2 scalac-hash v2.11.5 sandbox/test.scala && scala-hash v2.11.5 ammonite.Main 2>&1 | head -n3
scala.ScalaReflectionException: object ammonite.ops.ls not found.
    at scala.reflect.internal.Mirrors$RootsBase.staticModule(Mirrors.scala:162)
    at scala.reflect.internal.Mirrors$RootsBase.staticModule(Mirrors.scala:22)

% qscalac sandbox/test.scala && qscala ammonite.Main

% git log -1
commit 06e7e342d1e27097df0b9d0b31a322fd1cf0a34e
Author: Jason Zaugg <jza...@gmail.com>
Date:   Wed Feb 25 16:16:47 2015 +1000

    SI-9182 Fix runtime reflection with package object, overloads

    Eponymous modules and methods should be allowed to live in the
    same package scope. This can happen when using a module and
    and implicit class, or when defining the overloads manually.

    This commit tones back an assertion that was added for sanity checking
    runtime reflection thread safety to only fire when we are sure that
    neither the existing and current symbol of the given name are methods.
-jason

Reply all
Reply to author
Forward
0 new messages