diff options
Diffstat (limited to 'src/compiler/scala/reflect/reify/package.scala')
-rw-r--r-- | src/compiler/scala/reflect/reify/package.scala | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/src/compiler/scala/reflect/reify/package.scala b/src/compiler/scala/reflect/reify/package.scala index a253effc1c..a76f147dc4 100644 --- a/src/compiler/scala/reflect/reify/package.scala +++ b/src/compiler/scala/reflect/reify/package.scala @@ -1,6 +1,6 @@ package scala.reflect -import language.implicitConversions +import scala.language.implicitConversions import scala.reflect.base.{Universe => BaseUniverse} import scala.reflect.macros.{Context, ReificationError, UnexpectedReificationError} import scala.tools.nsc.Global @@ -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 } } |