diff options
author | Josh Suereth <joshua.suereth@gmail.com> | 2012-09-12 10:46:45 -0400 |
---|---|---|
committer | Josh Suereth <joshua.suereth@gmail.com> | 2012-09-13 13:04:23 -0400 |
commit | 7861ed6886ecf827907a6b48f0628395f199f49b (patch) | |
tree | feae260b291c0fe1a819dd3109ac3f841ca90a39 /src | |
parent | 76d4e9a8071f9e102106696664376b7f70622582 (diff) | |
download | scala-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.
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/reflect/reify/package.scala | 20 |
1 files changed, 18 insertions, 2 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 } } |