summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Suereth <joshua.suereth@gmail.com>2012-09-12 10:46:45 -0400
committerJosh Suereth <joshua.suereth@gmail.com>2012-09-13 13:04:23 -0400
commit7861ed6886ecf827907a6b48f0628395f199f49b (patch)
treefeae260b291c0fe1a819dd3109ac3f841ca90a39
parent76d4e9a8071f9e102106696664376b7f70622582 (diff)
downloadscala-7861ed6886ecf827907a6b48f0628395f199f49b.tar.gz
scala-7861ed6886ecf827907a6b48f0628395f199f49b.tar.bz2
scala-7861ed6886ecf827907a6b48f0628395f199f49b.zip
Fixes SI-6259. Unable to use typeOf in super call of top-level object.
This works around the issue of the inability to use classOf for top-level object classes by inventing a new anonymous class and instantiating it just to grab its class. Since the class is a nested type of the top-level object it'll be in the same classloader unless some kind of evil behavior is afoot. This patch should be undone if ever SI-2453 ever gets fixed, or we wind up with a direct way to grab the class of an object.
-rw-r--r--src/compiler/scala/reflect/reify/package.scala20
-rw-r--r--test/files/pos/t6259.scala47
-rw-r--r--test/files/run/toolbox_typecheck_macrosdisabled.check73
-rw-r--r--test/files/run/toolbox_typecheck_macrosdisabled.scala6
-rw-r--r--test/files/run/toolbox_typecheck_macrosdisabled2.check73
-rw-r--r--test/files/run/toolbox_typecheck_macrosdisabled2.scala4
6 files changed, 156 insertions, 67 deletions
diff --git a/src/compiler/scala/reflect/reify/package.scala b/src/compiler/scala/reflect/reify/package.scala
index a253effc1c..fab5699da6 100644
--- a/src/compiler/scala/reflect/reify/package.scala
+++ b/src/compiler/scala/reflect/reify/package.scala
@@ -26,7 +26,14 @@ package object reify {
private[reify] def mkDefaultMirrorRef(global: Global)(universe: global.Tree, typer0: global.analyzer.Typer): global.Tree = {
import global._
import definitions._
- val enclosingErasure = reifyEnclosingRuntimeClass(global)(typer0)
+ val enclosingErasure = {
+ val rClassTree = reifyEnclosingRuntimeClass(global)(typer0)
+ // HACK around SI-6259
+ // If we're in the constructor of an object or others don't have easy access to `this`, we have no good way to grab
+ // the class of that object. Instead, we construct an anonymous class and grab his class file, assuming
+ // this is enough to get the correct class loadeer for the class we *want* a mirror for, the object itself.
+ rClassTree orElse Apply(Select(treeBuilder.makeAnonymousNew(Nil), sn.GetClass), Nil)
+ }
// JavaUniverse is defined in scala-reflect.jar, so we must be very careful in case someone reifies stuff having only scala-library.jar on the classpath
val isJavaUniverse = JavaUniverseClass != NoSymbol && universe.tpe <:< JavaUniverseClass.toTypeConstructor
if (isJavaUniverse && !enclosingErasure.isEmpty) Apply(Select(universe, nme.runtimeMirror), List(Select(enclosingErasure, sn.GetClassLoader)))
@@ -61,6 +68,8 @@ package object reify {
}
}
+ // Note: If current context is inside the constructor of an object or otherwise not inside
+ // a class/object body, this will return an EmptyTree.
def reifyEnclosingRuntimeClass(global: Global)(typer0: global.analyzer.Typer): global.Tree = {
import global._
import definitions._
@@ -68,8 +77,15 @@ package object reify {
if (isThisInScope) {
val enclosingClasses = typer0.context.enclosingContextChain map (_.tree) collect { case classDef: ClassDef => classDef }
val classInScope = enclosingClasses.headOption getOrElse EmptyTree
+ def isUnsafeToUseThis = {
+ val isInsideConstructorSuper = typer0.context.enclosingContextChain exists (_.inSelfSuperCall)
+ // Note: It's ok to check for any object here, because if we were in an enclosing class, we'd already have returned its classOf
+ val isInsideObject = typer0.context.enclosingContextChain map (_.tree) exists { case _: ModuleDef => true; case _ => false }
+ isInsideConstructorSuper && isInsideObject
+ }
if (!classInScope.isEmpty) reifyRuntimeClass(global)(typer0, classInScope.symbol.toTypeConstructor, concrete = true)
- else Select(This(tpnme.EMPTY), sn.GetClass)
+ else if(!isUnsafeToUseThis) Select(This(tpnme.EMPTY), sn.GetClass)
+ else EmptyTree
} else EmptyTree
}
}
diff --git a/test/files/pos/t6259.scala b/test/files/pos/t6259.scala
new file mode 100644
index 0000000000..43361c417e
--- /dev/null
+++ b/test/files/pos/t6259.scala
@@ -0,0 +1,47 @@
+package t6259
+
+import scala.reflect.runtime.universe._
+
+class A[X](implicit val tt: TypeTag[X]) {}
+object B extends A[String]
+
+object C {
+ object D extends A[String]
+}
+
+trait E {
+ object F extends A[String]
+}
+
+class G {
+ object H extends A[String]
+}
+
+object Test {
+ val x = {
+ object InVal extends A[String]
+ 5
+ }
+
+}
+
+// Note: Both of these fail right now.
+
+trait NeedsEarly {
+ val x: AnyRef
+}
+
+object Early extends {
+ // Drops to this.getClass and is not ok...
+ val x = { object EarlyOk extends A[String]; EarlyOk }
+} with NeedsEarly
+
+
+class DoubleTrouble[X](x: AnyRef)(implicit override val tt: TypeTag[X]) extends A[X]
+
+object DoubleOk extends DoubleTrouble[String]({
+ // Drops to this.getClass and is an issue
+ object InnerTrouble extends A[String];
+ InnerTrouble
+})
+
diff --git a/test/files/run/toolbox_typecheck_macrosdisabled.check b/test/files/run/toolbox_typecheck_macrosdisabled.check
index 9cf101c69d..4d253f31fc 100644
--- a/test/files/run/toolbox_typecheck_macrosdisabled.check
+++ b/test/files/run/toolbox_typecheck_macrosdisabled.check
@@ -1,32 +1,41 @@
-{
- val $u: ru.type = ru;
- val $m: $u.Mirror = ru.rootMirror;
- $u.Expr.apply[Int(2)]($m, {
- final class $treecreator1 extends TreeCreator {
- def <init>(): $treecreator1 = {
- $treecreator1.super.<init>();
- ()
- };
- def apply[U <: scala.reflect.base.Universe with Singleton]($m$untyped: scala.reflect.base.MirrorOf[U]): U#Tree = {
- val $u: U = $m$untyped.universe;
- val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror];
- $u.Literal.apply($u.Constant.apply(2))
- }
- };
- new $treecreator1()
- })($u.TypeTag.apply[Int(2)]($m, {
- final class $typecreator2 extends TypeCreator {
- def <init>(): $typecreator2 = {
- $typecreator2.super.<init>();
- ()
- };
- def apply[U <: scala.reflect.base.Universe with Singleton]($m$untyped: scala.reflect.base.MirrorOf[U]): U#Type = {
- val $u: U = $m$untyped.universe;
- val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror];
- $u.ConstantType.apply($u.Constant.apply(2))
- }
- };
- new $typecreator2()
- }))
-}
-ru.reify[Int](2)
+{
+ val $u: ru.type = ru;
+ val $m: $u.Mirror = ru.runtimeMirror({
+ final class $anon extends scala.AnyRef {
+ def <init>(): anonymous class $anon = {
+ $anon.super.<init>();
+ ()
+ };
+ ()
+ };
+ new $anon()
+}.getClass().getClassLoader());
+ $u.Expr.apply[Int(2)]($m, {
+ final class $treecreator1 extends TreeCreator {
+ def <init>(): $treecreator1 = {
+ $treecreator1.super.<init>();
+ ()
+ };
+ def apply[U <: scala.reflect.base.Universe with Singleton]($m$untyped: scala.reflect.base.MirrorOf[U]): U#Tree = {
+ val $u: U = $m$untyped.universe;
+ val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror];
+ $u.Literal.apply($u.Constant.apply(2))
+ }
+ };
+ new $treecreator1()
+ })($u.TypeTag.apply[Int(2)]($m, {
+ final class $typecreator2 extends TypeCreator {
+ def <init>(): $typecreator2 = {
+ $typecreator2.super.<init>();
+ ()
+ };
+ def apply[U <: scala.reflect.base.Universe with Singleton]($m$untyped: scala.reflect.base.MirrorOf[U]): U#Type = {
+ val $u: U = $m$untyped.universe;
+ val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror];
+ $u.ConstantType.apply($u.Constant.apply(2))
+ }
+ };
+ new $typecreator2()
+ }))
+}
+ru.reify[Int](2)
diff --git a/test/files/run/toolbox_typecheck_macrosdisabled.scala b/test/files/run/toolbox_typecheck_macrosdisabled.scala
index bcbd637e02..01a418d42e 100644
--- a/test/files/run/toolbox_typecheck_macrosdisabled.scala
+++ b/test/files/run/toolbox_typecheck_macrosdisabled.scala
@@ -3,6 +3,10 @@ import scala.reflect.runtime.{universe => ru}
import scala.reflect.runtime.{currentMirror => cm}
import scala.tools.reflect.ToolBox
+// Note: If you're looking at this test and you don't know why, you may
+// have accidentally changed the way type tags reify. If so, validate
+// that your changes are accurate and update the check file.
+
object Test extends App {
val toolbox = cm.mkToolBox()
val rupkg = cm.staticModule("scala.reflect.runtime.package")
@@ -17,4 +21,4 @@ object Test extends App {
val tree2 = Apply(Select(Ident(ru), newTermName("reify")), List(Literal(Constant(2))))
val ttree2 = toolbox.typeCheck(tree2, withMacrosDisabled = true)
println(ttree2)
-} \ No newline at end of file
+}
diff --git a/test/files/run/toolbox_typecheck_macrosdisabled2.check b/test/files/run/toolbox_typecheck_macrosdisabled2.check
index d344e33180..149c3def12 100644
--- a/test/files/run/toolbox_typecheck_macrosdisabled2.check
+++ b/test/files/run/toolbox_typecheck_macrosdisabled2.check
@@ -1,32 +1,41 @@
-{
- val $u: ru.type = ru;
- val $m: $u.Mirror = ru.rootMirror;
- $u.Expr.apply[Array[Int]]($m, {
- final class $treecreator1 extends TreeCreator {
- def <init>(): $treecreator1 = {
- $treecreator1.super.<init>();
- ()
- };
- def apply[U <: scala.reflect.base.Universe with Singleton]($m$untyped: scala.reflect.base.MirrorOf[U]): U#Tree = {
- val $u: U = $m$untyped.universe;
- val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror];
- $u.Apply.apply($u.Select.apply($u.Select.apply($u.build.Ident($m.staticPackage("scala")), $u.newTermName("Array")), $u.newTermName("apply")), scala.collection.immutable.List.apply[$u.Literal]($u.Literal.apply($u.Constant.apply(2))))
- }
- };
- new $treecreator1()
- })($u.TypeTag.apply[Array[Int]]($m, {
- final class $typecreator2 extends TypeCreator {
- def <init>(): $typecreator2 = {
- $typecreator2.super.<init>();
- ()
- };
- def apply[U <: scala.reflect.base.Universe with Singleton]($m$untyped: scala.reflect.base.MirrorOf[U]): U#Type = {
- val $u: U = $m$untyped.universe;
- val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror];
- $u.TypeRef.apply($u.ThisType.apply($m.staticPackage("scala").asModule.moduleClass), $m.staticClass("scala.Array"), scala.collection.immutable.List.apply[$u.Type]($m.staticClass("scala.Int").asType.toTypeConstructor))
- }
- };
- new $typecreator2()
- }))
-}
-ru.reify[Array[Int]](scala.Array.apply(2))
+{
+ val $u: ru.type = ru;
+ val $m: $u.Mirror = ru.runtimeMirror({
+ final class $anon extends scala.AnyRef {
+ def <init>(): anonymous class $anon = {
+ $anon.super.<init>();
+ ()
+ };
+ ()
+ };
+ new $anon()
+}.getClass().getClassLoader());
+ $u.Expr.apply[Array[Int]]($m, {
+ final class $treecreator1 extends TreeCreator {
+ def <init>(): $treecreator1 = {
+ $treecreator1.super.<init>();
+ ()
+ };
+ def apply[U <: scala.reflect.base.Universe with Singleton]($m$untyped: scala.reflect.base.MirrorOf[U]): U#Tree = {
+ val $u: U = $m$untyped.universe;
+ val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror];
+ $u.Apply.apply($u.Select.apply($u.Select.apply($u.build.Ident($m.staticPackage("scala")), $u.newTermName("Array")), $u.newTermName("apply")), scala.collection.immutable.List.apply[$u.Literal]($u.Literal.apply($u.Constant.apply(2))))
+ }
+ };
+ new $treecreator1()
+ })($u.TypeTag.apply[Array[Int]]($m, {
+ final class $typecreator2 extends TypeCreator {
+ def <init>(): $typecreator2 = {
+ $typecreator2.super.<init>();
+ ()
+ };
+ def apply[U <: scala.reflect.base.Universe with Singleton]($m$untyped: scala.reflect.base.MirrorOf[U]): U#Type = {
+ val $u: U = $m$untyped.universe;
+ val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror];
+ $u.TypeRef.apply($u.ThisType.apply($m.staticPackage("scala").asModule.moduleClass), $m.staticClass("scala.Array"), scala.collection.immutable.List.apply[$u.Type]($m.staticClass("scala.Int").asType.toTypeConstructor))
+ }
+ };
+ new $typecreator2()
+ }))
+}
+ru.reify[Array[Int]](scala.Array.apply(2))
diff --git a/test/files/run/toolbox_typecheck_macrosdisabled2.scala b/test/files/run/toolbox_typecheck_macrosdisabled2.scala
index 51493ffc1c..462dc9fa91 100644
--- a/test/files/run/toolbox_typecheck_macrosdisabled2.scala
+++ b/test/files/run/toolbox_typecheck_macrosdisabled2.scala
@@ -3,6 +3,10 @@ import scala.reflect.runtime.{universe => ru}
import scala.reflect.runtime.{currentMirror => cm}
import scala.tools.reflect.ToolBox
+// Note: If you're looking at this test and you don't know why, you may
+// have accidentally changed the way type tags reify. If so, validate
+// that your changes are accurate and update the check file.
+
object Test extends App {
val toolbox = cm.mkToolBox()
val rupkg = cm.staticModule("scala.reflect.runtime.package")