diff options
author | Paul Phillips <paulp@improving.org> | 2013-01-25 09:06:08 -0800 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-01-25 09:06:08 -0800 |
commit | dacab70646561159b4c34c2d751e03b61eeee369 (patch) | |
tree | 985c157d370b2af30987ff0bfa5ab885a9e4f4b0 /src | |
parent | b49eaefd816a80ad7d04b150c16f8e76cfbdb03e (diff) | |
parent | 1a7de4314ac72bca81e31ad3ac0af7bee7eed26b (diff) | |
download | scala-dacab70646561159b4c34c2d751e03b61eeee369.tar.gz scala-dacab70646561159b4c34c2d751e03b61eeee369.tar.bz2 scala-dacab70646561159b4c34c2d751e03b61eeee369.zip |
Merge pull request #1938 from retronym/ticket/6666
SI-6666 Restrict hidden `this` access in self/super calls.
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/LambdaLift.scala | 38 |
1 files changed, 31 insertions, 7 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala index 4a23e65ad2..a4f75f424f 100644 --- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala +++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala @@ -320,12 +320,24 @@ abstract class LambdaLift extends InfoTransform { private def memberRef(sym: Symbol) = { val clazz = sym.owner.enclClass //Console.println("memberRef from "+currentClass+" to "+sym+" in "+clazz) - val qual = if (clazz == currentClass) gen.mkAttributedThis(clazz) - else { - sym resetFlag(LOCAL | PRIVATE) - if (clazz.isStaticOwner) gen.mkAttributedQualifier(clazz.thisType) - else outerPath(outerValue, currentClass.outerClass, clazz) - } + def prematureSelfReference() { + val what = + if (clazz.isStaticOwner) clazz.fullLocationString + else s"the unconstructed `this` of ${clazz.fullLocationString}" + val msg = s"Implementation restriction: access of ${sym.fullLocationString} from ${currentClass.fullLocationString}, would require illegal premature access to $what" + currentUnit.error(curTree.pos, msg) + } + val qual = + if (clazz == currentClass) gen.mkAttributedThis(clazz) + else { + sym resetFlag (LOCAL | PRIVATE) + if (selfOrSuperCalls exists (_.owner == clazz)) { + prematureSelfReference() + EmptyTree + } + else if (clazz.isStaticOwner) gen.mkAttributedQualifier(clazz.thisType) + else outerPath(outerValue, currentClass.outerClass, clazz) + } Select(qual, sym) setType sym.tpe } @@ -495,13 +507,25 @@ abstract class LambdaLift extends InfoTransform { private def preTransform(tree: Tree) = super.transform(tree) setType lifted(tree.tpe) + /** The stack of constructor symbols in which a call to this() or to the super + * constructor is active. + */ + private val selfOrSuperCalls = mutable.Stack[Symbol]() + @inline private def inSelfOrSuperCall[A](sym: Symbol)(a: => A) = try { + selfOrSuperCalls push sym + a + } finally selfOrSuperCalls.pop() + override def transform(tree: Tree): Tree = tree match { case Select(ReferenceToBoxed(idt), elem) if elem == nme.elem => postTransform(preTransform(idt), isBoxedRef = false) case ReferenceToBoxed(idt) => postTransform(preTransform(idt), isBoxedRef = true) case _ => - postTransform(preTransform(tree)) + def transformTree = postTransform(preTransform(tree)) + if (treeInfo isSelfOrSuperConstrCall tree) + inSelfOrSuperCall(currentOwner)(transformTree) + else transformTree } /** Transform statements and add lifted definitions to them. */ |