aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/transform/ExplicitOuter.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-03-11 10:47:27 +0100
committerMartin Odersky <odersky@gmail.com>2016-03-12 14:25:01 +0100
commite5cad0c2ccfd4e8ea3dfb9f0eb22ab0a958287f8 (patch)
tree9675f2c6fe60cc42cad513feb6b1463473785899 /src/dotty/tools/dotc/transform/ExplicitOuter.scala
parente68d68414fa346fad9dee204746d826ee172e861 (diff)
downloaddotty-e5cad0c2ccfd4e8ea3dfb9f0eb22ab0a958287f8.tar.gz
dotty-e5cad0c2ccfd4e8ea3dfb9f0eb22ab0a958287f8.tar.bz2
dotty-e5cad0c2ccfd4e8ea3dfb9f0eb22ab0a958287f8.zip
Refinements to referencesOuter
In a New we need to decide based on the prefix of the type of object created.
Diffstat (limited to 'src/dotty/tools/dotc/transform/ExplicitOuter.scala')
-rw-r--r--src/dotty/tools/dotc/transform/ExplicitOuter.scala41
1 files changed, 24 insertions, 17 deletions
diff --git a/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/src/dotty/tools/dotc/transform/ExplicitOuter.scala
index 4cf076c45..9170cd277 100644
--- a/src/dotty/tools/dotc/transform/ExplicitOuter.scala
+++ b/src/dotty/tools/dotc/transform/ExplicitOuter.scala
@@ -212,27 +212,34 @@ object ExplicitOuter {
/** Tree references an outer class of `cls` which is not a static owner.
*/
def referencesOuter(cls: Symbol, tree: Tree)(implicit ctx: Context): Boolean = {
- def isOuter(sym: Symbol) =
+ def isOuterSym(sym: Symbol) =
!sym.isStaticOwner && cls.isProperlyContainedIn(sym)
+ def isOuterRef(ref: Type): Boolean = ref match {
+ case ref: ThisType =>
+ isOuterSym(ref.cls)
+ case ref: TermRef =>
+ if (ref.prefix ne NoPrefix)
+ !ref.symbol.isStatic && isOuterRef(ref.prefix)
+ else if (ref.symbol is Hoistable)
+ // ref.symbol will be placed in enclosing class scope by LambdaLift, so it might need
+ // an outer path then.
+ isOuterSym(ref.symbol.owner.enclosingClass)
+ else
+ // ref.symbol will get a proxy in immediately enclosing class. If this properly
+ // contains the current class, it needs an outer path.
+ ctx.owner.enclosingClass.owner.enclosingClass.isContainedIn(ref.symbol.owner)
+ case _ => false
+ }
+ def hasOuterPrefix(tp: Type) = tp match {
+ case TypeRef(prefix, _) => isOuterRef(prefix)
+ case _ => false
+ }
tree match {
- case thisTree @ This(_) =>
- isOuter(thisTree.symbol)
- case id: Ident =>
- id.tpe match {
- case ref @ TermRef(NoPrefix, _) =>
- if (ref.symbol is Hoistable)
- // ref.symbol will be placed in enclosing class scope by LambdaLift, so it might need
- // an outer path then.
- isOuter(ref.symbol.owner.enclosingClass)
- else
- // ref.symbol will get a proxy in immediately enclosing class. If this properly
- // contains the current class, it needs an outer path.
- ctx.owner.enclosingClass.owner.enclosingClass.isContainedIn(ref.symbol.owner)
- case _ => false
- }
+ case _: This | _: Ident => isOuterRef(tree.tpe)
case nw: New =>
val newCls = nw.tpe.classSymbol
- isOuter(newCls.owner.enclosingClass) ||
+ isOuterSym(newCls.owner.enclosingClass) ||
+ hasOuterPrefix(nw.tpe) ||
newCls.owner.isTerm && cls.isProperlyContainedIn(newCls)
// newCls might get proxies for free variables. If current class is
// properly contained in newCls, it needs an outer path to newCls access the