diff --git a/src/dotty/tools/dotc/transform/Constructors.scala b/src/dotty/tools/dotc/transform/Constructors.scala index 100e9ff211c8..1d94b3552c0e 100644 --- a/src/dotty/tools/dotc/transform/Constructors.scala +++ b/src/dotty/tools/dotc/transform/Constructors.scala @@ -156,6 +156,20 @@ class Constructors extends MiniPhaseTransform with SymTransformer { thisTransfor val constrStats, clsStats = new mutable.ListBuffer[Tree] + /** Map outer getters $outer and outer accessors $A$B$$$outer to the given outer parameter. */ + def mapOuter(outerParam: Symbol) = new TreeMap { + override def transform(tree: Tree)(implicit ctx: Context) = tree match { + case Apply(fn, Nil) + if (fn.symbol.is(OuterAccessor) + || fn.symbol.isGetter && fn.symbol.name == nme.OUTER + ) && + fn.symbol.info.resultType.classSymbol == outerParam.info.classSymbol => + ref(outerParam) + case _ => + super.transform(tree) + } + } + // Split class body into statements that go into constructor and // definitions that are kept as members of the class. def splitStats(stats: List[Tree]): Unit = stats match { @@ -174,6 +188,8 @@ class Constructors extends MiniPhaseTransform with SymTransformer { thisTransfor owner = constr.symbol).installAfter(thisTransform) constrStats += intoConstr(stat, sym) } + case DefDef(nme.CONSTRUCTOR, _, ((outerParam @ ValDef(nme.OUTER, _, _)) :: _) :: Nil, _, _) => + clsStats += mapOuter(outerParam.symbol).transform(stat) case _: DefTree => clsStats += stat case _ => @@ -221,9 +237,15 @@ class Constructors extends MiniPhaseTransform with SymTransformer { thisTransfor case stats => (Nil, stats) } + val mappedSuperCalls = vparams match { + case (outerParam @ ValDef(nme.OUTER, _, _)) :: _ => + superCalls.map(mapOuter(outerParam.symbol).transform) + case _ => superCalls + } + cpy.Template(tree)( constr = cpy.DefDef(constr)( - rhs = Block(superCalls ::: copyParams ::: followConstrStats, unitLiteral)), + rhs = Block(mappedSuperCalls ::: copyParams ::: followConstrStats, unitLiteral)), body = clsStats.toList) } } diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala index 1664db456124..962297517fad 100644 --- a/src/dotty/tools/dotc/transform/Erasure.scala +++ b/src/dotty/tools/dotc/transform/Erasure.scala @@ -479,7 +479,9 @@ object Erasure extends TypeTestsCasts{ val MethodType(pnames, ptypes) = sym.info.resultType effectiveSym = sym.copy(info = MethodType(pnames, ptypes, defn.ObjectType)) } - val restpe = effectiveSym.info.resultType + val restpe = + if (effectiveSym.isConstructor) defn.UnitType + else effectiveSym.info.resultType val ddef1 = untpd.cpy.DefDef(ddef)( tparams = Nil, vparamss = (outer.paramDefs(effectiveSym) ::: ddef.vparamss.flatten) :: Nil, diff --git a/src/dotty/tools/dotc/transform/LambdaLift.scala b/src/dotty/tools/dotc/transform/LambdaLift.scala index 41d6f3c438c4..043c92737fdc 100644 --- a/src/dotty/tools/dotc/transform/LambdaLift.scala +++ b/src/dotty/tools/dotc/transform/LambdaLift.scala @@ -391,11 +391,24 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform val freeParamDefs = ownProxies.map(proxy => transformFollowingDeep(ValDef(proxy.asTerm).withPos(tree.pos)).asInstanceOf[ValDef]) def proxyInit(field: Symbol, param: Symbol) = - transformFollowingDeep(ref(field).becomes(ref(param))) + transformFollowingDeep(memberRef(field).becomes(ref(param))) + + /** Map references to proxy fields `this.proxy` to proxy parameters */ + def mapProxies = new TreeMap { + override def transform(tree: Tree)(implicit ctx: Context) = tree match { + case Select(This(_), _) if proxies contains tree.symbol => + ref(tree.symbol.subst(proxies, ownProxies)) + case _ => + super.transform(tree) + } + } + + /** Initialize proxy fields from proxy parameters and map `rhs` from fields to parameters */ def copyParams(rhs: Tree) = { ctx.log(i"copy params ${proxies.map(_.showLocated)}%, %, own = ${ownProxies.map(_.showLocated)}%, %") - seq((proxies, ownProxies).zipped.map(proxyInit), rhs) + seq((proxies, ownProxies).zipped.map(proxyInit), mapProxies.transform(rhs)) } + tree match { case tree: DefDef => cpy.DefDef(tree)( diff --git a/src/dotty/tools/dotc/transform/LazyVals.scala b/src/dotty/tools/dotc/transform/LazyVals.scala index e52e2537c8dd..b57e4c5926e3 100644 --- a/src/dotty/tools/dotc/transform/LazyVals.scala +++ b/src/dotty/tools/dotc/transform/LazyVals.scala @@ -68,11 +68,16 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer { appendOffsetDefs.get(cls) match { case None => template case Some(data) => - cpy.Template(template)(body = data.defs ::: template.body) + cpy.Template(template)(body = addInFront(data.defs, template.body)) } } + private def addInFront(prefix: List[Tree], stats: List[Tree]) = stats match { + case first :: rest if isSuperConstrCall(first) => first :: prefix ::: rest + case _ => prefix ::: stats + } + /** Replace a local lazy val inside a method, * with a LazyHolder from * dotty.runtime(eg dotty.runtime.LazyInt) diff --git a/tests/pending/run/NestedClasses.check b/tests/run/NestedClasses.check similarity index 100% rename from tests/pending/run/NestedClasses.check rename to tests/run/NestedClasses.check diff --git a/tests/pending/run/NestedClasses.scala b/tests/run/NestedClasses.scala similarity index 100% rename from tests/pending/run/NestedClasses.scala rename to tests/run/NestedClasses.scala diff --git a/tests/pending/run/constructors.check b/tests/run/constructors.check similarity index 100% rename from tests/pending/run/constructors.check rename to tests/run/constructors.check diff --git a/tests/pending/run/constructors.scala b/tests/run/constructors.scala similarity index 91% rename from tests/pending/run/constructors.scala rename to tests/run/constructors.scala index 90926431f967..19afc3d678e3 100644 --- a/tests/pending/run/constructors.scala +++ b/tests/run/constructors.scala @@ -4,8 +4,9 @@ class A(x: Int, y: Int) { def this(x: Int) = this(x, x); def this() = this(1); override def toString() = "x=" + x + " y=" + y; - class B(a: Int, b: Int, c: String) { + class B(val a: Int, b: Int, c: String) { def this(str: String) = this(x, y, str); + val xx = a override def toString() = "x=" + x + " y=" + y + " a=" + a + " b=" + b + " c=" + c; } diff --git a/tests/pending/run/shortClass.check b/tests/run/shortClass.check similarity index 81% rename from tests/pending/run/shortClass.check rename to tests/run/shortClass.check index fbdb725ccaa0..0c62fb26f28f 100644 --- a/tests/pending/run/shortClass.check +++ b/tests/run/shortClass.check @@ -1,8 +1,8 @@ bippity.bop.Foo bippity.bop.Foo$Bar bippity.bop.Foo$Bar$ -Test$$anon$1 -Test$$anon$2 +Test$$anon$ +Test$$anon$ Foo Bar Bar$ diff --git a/tests/pending/run/shortClass.scala b/tests/run/shortClass.scala similarity index 66% rename from tests/pending/run/shortClass.scala rename to tests/run/shortClass.scala index b7bb0168963a..c5c2043f4dd0 100644 --- a/tests/pending/run/shortClass.scala +++ b/tests/run/shortClass.scala @@ -15,10 +15,12 @@ object Test { import bippity._ import bop._ + def printSanitized(x: String) = println(x.filterNot(_.isDigit)) + def main(args: Array[String]): Unit = { val f = new Foo val instances = List(f, new f.Bar, f.Bar, new Foo with DingDongBippy, new f.Bar with DingDongBippy) - instances map (_.getClass.getName) foreach println - instances map shortClassOfInstance foreach println + instances map (_.getClass.getName) foreach printSanitized + instances map shortClassOfInstance foreach printSanitized } } diff --git a/tests/pending/run/t8611b.flags b/tests/run/t8611b.flags similarity index 100% rename from tests/pending/run/t8611b.flags rename to tests/run/t8611b.flags diff --git a/tests/pending/run/t8611b.scala b/tests/run/t8611b.scala similarity index 100% rename from tests/pending/run/t8611b.scala rename to tests/run/t8611b.scala