diff options
author | Martin Odersky <odersky@gmail.com> | 2016-03-11 10:47:27 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-03-12 14:25:01 +0100 |
commit | e5cad0c2ccfd4e8ea3dfb9f0eb22ab0a958287f8 (patch) | |
tree | 9675f2c6fe60cc42cad513feb6b1463473785899 /src | |
parent | e68d68414fa346fad9dee204746d826ee172e861 (diff) | |
download | dotty-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')
-rw-r--r-- | src/dotty/tools/dotc/transform/ExplicitOuter.scala | 41 |
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 |