Skip to content

Commit 01269e9

Browse files
committed
Merge pull request #1168 from dotty-staging/fix-#1131
Tweaks to ExplicitOuter and TreeTypeMap
2 parents 802de86 + 5f2c21b commit 01269e9

File tree

5 files changed

+43
-33
lines changed

5 files changed

+43
-33
lines changed

src/dotty/tools/dotc/ast/TreeTypeMap.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ final class TreeTypeMap(
8282
constr = tmap.transformSub(constr),
8383
parents = parents mapconserve transform,
8484
self = tmap.transformSub(self),
85-
body = impl.body mapconserve tmap.transform
85+
body = impl.body mapconserve
86+
(tmap.transform(_)(ctx.withOwner(mapOwner(impl.symbol.owner))))
8687
).withType(tmap.mapType(impl.tpe))
8788
case tree1 =>
8889
tree1.withType(mapType(tree1.tpe)) match {

src/dotty/tools/dotc/transform/Constructors.scala

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import collection.mutable
2626
* - also moves private fields that are accessed only from constructor
2727
* into the constructor if possible.
2828
*/
29-
class Constructors extends MiniPhaseTransform with SymTransformer { thisTransform =>
29+
class Constructors extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform =>
3030
import tpd._
3131

3232
override def phaseName: String = "constructors"
@@ -99,18 +99,6 @@ class Constructors extends MiniPhaseTransform with SymTransformer { thisTransfor
9999
}
100100
}
101101

102-
/** Symbols that are owned by either <local dummy> or a class field move into the
103-
* primary constructor.
104-
*/
105-
override def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation = {
106-
def ownerBecomesConstructor(owner: Symbol): Boolean =
107-
(owner.isLocalDummy || owner.isTerm && !owner.is(MethodOrLazy)) &&
108-
owner.owner.isClass
109-
if (ownerBecomesConstructor(sym.owner))
110-
sym.copySymDenotation(owner = sym.owner.enclosingClass.primaryConstructor)
111-
else sym
112-
}
113-
114102
/** @return true if after ExplicitOuter, all references from this tree go via an
115103
* outer link, so no parameter accessors need to be rewired to parameters
116104
*/

src/dotty/tools/dotc/transform/ExplicitOuter.scala

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -212,27 +212,34 @@ object ExplicitOuter {
212212
/** Tree references an outer class of `cls` which is not a static owner.
213213
*/
214214
def referencesOuter(cls: Symbol, tree: Tree)(implicit ctx: Context): Boolean = {
215-
def isOuter(sym: Symbol) =
215+
def isOuterSym(sym: Symbol) =
216216
!sym.isStaticOwner && cls.isProperlyContainedIn(sym)
217+
def isOuterRef(ref: Type): Boolean = ref match {
218+
case ref: ThisType =>
219+
isOuterSym(ref.cls)
220+
case ref: TermRef =>
221+
if (ref.prefix ne NoPrefix)
222+
!ref.symbol.isStatic && isOuterRef(ref.prefix)
223+
else if (ref.symbol is Hoistable)
224+
// ref.symbol will be placed in enclosing class scope by LambdaLift, so it might need
225+
// an outer path then.
226+
isOuterSym(ref.symbol.owner.enclosingClass)
227+
else
228+
// ref.symbol will get a proxy in immediately enclosing class. If this properly
229+
// contains the current class, it needs an outer path.
230+
ctx.owner.enclosingClass.owner.enclosingClass.isContainedIn(ref.symbol.owner)
231+
case _ => false
232+
}
233+
def hasOuterPrefix(tp: Type) = tp match {
234+
case TypeRef(prefix, _) => isOuterRef(prefix)
235+
case _ => false
236+
}
217237
tree match {
218-
case thisTree @ This(_) =>
219-
isOuter(thisTree.symbol)
220-
case id: Ident =>
221-
id.tpe match {
222-
case ref @ TermRef(NoPrefix, _) =>
223-
if (ref.symbol is Hoistable)
224-
// ref.symbol will be placed in enclosing class scope by LambdaLift, so it might need
225-
// an outer path then.
226-
isOuter(ref.symbol.owner.enclosingClass)
227-
else
228-
// ref.symbol will get a proxy in immediately enclosing class. If this properly
229-
// contains the current class, it needs an outer path.
230-
ctx.owner.enclosingClass.owner.enclosingClass.isContainedIn(ref.symbol.owner)
231-
case _ => false
232-
}
238+
case _: This | _: Ident => isOuterRef(tree.tpe)
233239
case nw: New =>
234240
val newCls = nw.tpe.classSymbol
235-
isOuter(newCls.owner.enclosingClass) ||
241+
isOuterSym(newCls.owner.enclosingClass) ||
242+
hasOuterPrefix(nw.tpe) ||
236243
newCls.owner.isTerm && cls.isProperlyContainedIn(newCls)
237244
// newCls might get proxies for free variables. If current class is
238245
// properly contained in newCls, it needs an outer path to newCls access the

src/dotty/tools/dotc/transform/Mixin.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform =>
140140
val vsym = stat.symbol
141141
val isym = initializer(vsym)
142142
val rhs = Block(
143-
initBuf.toList.map(_.changeOwner(impl.symbol, isym)),
144-
stat.rhs.changeOwner(vsym, isym).wildcardToDefault)
143+
initBuf.toList.map(_.changeOwnerAfter(impl.symbol, isym, thisTransform)),
144+
stat.rhs.changeOwnerAfter(vsym, isym, thisTransform).wildcardToDefault)
145145
initBuf.clear()
146146
cpy.DefDef(stat)(rhs = EmptyTree) :: DefDef(isym, rhs) :: Nil
147147
case stat: DefDef if stat.symbol.isSetter =>

tests/pos/i1131.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
class Outer {
2+
class Inner
3+
}
4+
5+
trait MustBeATrait {
6+
val o = new Outer
7+
val inner = {
8+
class C {
9+
new o.Inner
10+
}
11+
new C
12+
}
13+
val inner2 = new o.Inner {}
14+
}

0 commit comments

Comments
 (0)