diff options
author | Josh Suereth <Joshua.Suereth@gmail.com> | 2012-09-13 12:28:33 -0700 |
---|---|---|
committer | Josh Suereth <Joshua.Suereth@gmail.com> | 2012-09-13 12:28:33 -0700 |
commit | 62c1dffe4f72a3fb3bd04631c0b392843d97ee5b (patch) | |
tree | feae260b291c0fe1a819dd3109ac3f841ca90a39 | |
parent | 76d4e9a8071f9e102106696664376b7f70622582 (diff) | |
parent | 7861ed6886ecf827907a6b48f0628395f199f49b (diff) | |
download | scala-62c1dffe4f72a3fb3bd04631c0b392843d97ee5b.tar.gz scala-62c1dffe4f72a3fb3bd04631c0b392843d97ee5b.tar.bz2 scala-62c1dffe4f72a3fb3bd04631c0b392843d97ee5b.zip |
Merge pull request #1292 from jsuereth/fix/SI-6259
Fixes SI-6259. Unable to use typeOf in super call of top-level object.
-rw-r--r-- | src/compiler/scala/reflect/reify/package.scala | 20 | ||||
-rw-r--r-- | test/files/pos/t6259.scala | 47 | ||||
-rw-r--r-- | test/files/run/toolbox_typecheck_macrosdisabled.check | 73 | ||||
-rw-r--r-- | test/files/run/toolbox_typecheck_macrosdisabled.scala | 6 | ||||
-rw-r--r-- | test/files/run/toolbox_typecheck_macrosdisabled2.check | 73 | ||||
-rw-r--r-- | test/files/run/toolbox_typecheck_macrosdisabled2.scala | 4 |
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") |