aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/ast/TreeTypeMap.scala3
-rw-r--r--src/dotty/tools/dotc/transform/Constructors.scala14
-rw-r--r--src/dotty/tools/dotc/transform/ExplicitOuter.scala41
-rw-r--r--src/dotty/tools/dotc/transform/Mixin.scala4
-rw-r--r--tests/pos/i1131.scala14
5 files changed, 43 insertions, 33 deletions
diff --git a/src/dotty/tools/dotc/ast/TreeTypeMap.scala b/src/dotty/tools/dotc/ast/TreeTypeMap.scala
index d714a3d21..a35fe2e8f 100644
--- a/src/dotty/tools/dotc/ast/TreeTypeMap.scala
+++ b/src/dotty/tools/dotc/ast/TreeTypeMap.scala
@@ -82,7 +82,8 @@ final class TreeTypeMap(
constr = tmap.transformSub(constr),
parents = parents mapconserve transform,
self = tmap.transformSub(self),
- body = impl.body mapconserve tmap.transform
+ body = impl.body mapconserve
+ (tmap.transform(_)(ctx.withOwner(mapOwner(impl.symbol.owner))))
).withType(tmap.mapType(impl.tpe))
case tree1 =>
tree1.withType(mapType(tree1.tpe)) match {
diff --git a/src/dotty/tools/dotc/transform/Constructors.scala b/src/dotty/tools/dotc/transform/Constructors.scala
index b6ebd7d90..44638ce48 100644
--- a/src/dotty/tools/dotc/transform/Constructors.scala
+++ b/src/dotty/tools/dotc/transform/Constructors.scala
@@ -26,7 +26,7 @@ import collection.mutable
* - also moves private fields that are accessed only from constructor
* into the constructor if possible.
*/
-class Constructors extends MiniPhaseTransform with SymTransformer { thisTransform =>
+class Constructors extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform =>
import tpd._
override def phaseName: String = "constructors"
@@ -99,18 +99,6 @@ class Constructors extends MiniPhaseTransform with SymTransformer { thisTransfor
}
}
- /** Symbols that are owned by either <local dummy> or a class field move into the
- * primary constructor.
- */
- override def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation = {
- def ownerBecomesConstructor(owner: Symbol): Boolean =
- (owner.isLocalDummy || owner.isTerm && !owner.is(MethodOrLazy)) &&
- owner.owner.isClass
- if (ownerBecomesConstructor(sym.owner))
- sym.copySymDenotation(owner = sym.owner.enclosingClass.primaryConstructor)
- else sym
- }
-
/** @return true if after ExplicitOuter, all references from this tree go via an
* outer link, so no parameter accessors need to be rewired to parameters
*/
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
diff --git a/src/dotty/tools/dotc/transform/Mixin.scala b/src/dotty/tools/dotc/transform/Mixin.scala
index 3ec2aedcb..b0d1e5c5f 100644
--- a/src/dotty/tools/dotc/transform/Mixin.scala
+++ b/src/dotty/tools/dotc/transform/Mixin.scala
@@ -140,8 +140,8 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform =>
val vsym = stat.symbol
val isym = initializer(vsym)
val rhs = Block(
- initBuf.toList.map(_.changeOwner(impl.symbol, isym)),
- stat.rhs.changeOwner(vsym, isym).wildcardToDefault)
+ initBuf.toList.map(_.changeOwnerAfter(impl.symbol, isym, thisTransform)),
+ stat.rhs.changeOwnerAfter(vsym, isym, thisTransform).wildcardToDefault)
initBuf.clear()
cpy.DefDef(stat)(rhs = EmptyTree) :: DefDef(isym, rhs) :: Nil
case stat: DefDef if stat.symbol.isSetter =>
diff --git a/tests/pos/i1131.scala b/tests/pos/i1131.scala
new file mode 100644
index 000000000..42c2a685c
--- /dev/null
+++ b/tests/pos/i1131.scala
@@ -0,0 +1,14 @@
+class Outer {
+ class Inner
+}
+
+trait MustBeATrait {
+ val o = new Outer
+ val inner = {
+ class C {
+ new o.Inner
+ }
+ new C
+ }
+ val inner2 = new o.Inner {}
+}