diff options
author | odersky <odersky@gmail.com> | 2015-06-19 17:01:59 +0200 |
---|---|---|
committer | odersky <odersky@gmail.com> | 2015-06-19 17:01:59 +0200 |
commit | ad6c4ad920bfed6c7c9a87850f51433260a2acf5 (patch) | |
tree | 944fa514d1d5a84229211e8f6895722b99a2d249 | |
parent | c54debead6d12527469b9d69f4ab0d54cc13f7e9 (diff) | |
parent | 25304a028e6d1426b14ead4a469c362b8536d893 (diff) | |
download | dotty-ad6c4ad920bfed6c7c9a87850f51433260a2acf5.tar.gz dotty-ad6c4ad920bfed6c7c9a87850f51433260a2acf5.tar.bz2 dotty-ad6c4ad920bfed6c7c9a87850f51433260a2acf5.zip |
Merge pull request #671 from dotty-staging/fix/#659-lambdalift-proxies
Fix/#659 lambdalift proxies
-rw-r--r-- | src/dotty/tools/dotc/ast/tpd.scala | 9 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/ExplicitOuter.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/LambdaLift.scala | 15 | ||||
-rw-r--r-- | tests/run/i659.scala | 26 |
4 files changed, 49 insertions, 7 deletions
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala index 51011f90b..a35e0e523 100644 --- a/src/dotty/tools/dotc/ast/tpd.scala +++ b/src/dotty/tools/dotc/ast/tpd.scala @@ -76,8 +76,13 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { def Block(stats: List[Tree], expr: Tree)(implicit ctx: Context): Block = ta.assignType(untpd.Block(stats, expr), stats, expr) - def maybeBlock(stats: List[Tree], expr: Tree)(implicit ctx: Context): Tree = - if (stats.isEmpty) expr else Block(stats, expr) + /** Join `stats` in front of `expr` creating a new block if necessary */ + def seq(stats: List[Tree], expr: Tree)(implicit ctx: Context): Tree = + if (stats.isEmpty) expr + else expr match { + case Block(estats, eexpr) => cpy.Block(expr)(stats ::: estats, eexpr) + case _ => Block(stats, expr) + } def If(cond: Tree, thenp: Tree, elsep: Tree)(implicit ctx: Context): If = ta.assignType(untpd.If(cond, thenp, elsep), thenp, elsep) diff --git a/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/src/dotty/tools/dotc/transform/ExplicitOuter.scala index 912bc9b7f..eb231bfe7 100644 --- a/src/dotty/tools/dotc/transform/ExplicitOuter.scala +++ b/src/dotty/tools/dotc/transform/ExplicitOuter.scala @@ -136,7 +136,9 @@ object ExplicitOuter { /** A new outer accessor or param accessor */ private def newOuterSym(owner: ClassSymbol, cls: ClassSymbol, name: TermName, flags: FlagSet)(implicit ctx: Context) = { - ctx.newSymbol(owner, name, Synthetic | flags, cls.owner.enclosingClass.typeRef, coord = cls.coord) + val target = cls.owner.enclosingClass.typeRef + val info = if (flags.is(Method)) ExprType(target) else target + ctx.newSymbol(owner, name, Synthetic | flags, info, coord = cls.coord) } /** A new param accessor for the outer field in class `cls` */ @@ -302,7 +304,7 @@ object ExplicitOuter { val outerAccessorCtx = ctx.withPhaseNoLater(ctx.lambdaLiftPhase) // lambdalift mangles local class names, which means we cannot reliably find outer acessors anymore ctx.log(i"outer to $toCls of $tree: ${tree.tpe}, looking for ${outerAccName(treeCls.asClass)(outerAccessorCtx)} in $treeCls") if (treeCls == toCls) tree - else loop(tree select outerAccessor(treeCls.asClass)(outerAccessorCtx)) + else loop(tree.select(outerAccessor(treeCls.asClass)(outerAccessorCtx)).ensureApplied) } ctx.log(i"computing outerpath to $toCls from ${ctx.outersIterator.map(_.owner).toList}") loop(This(ctx.owner.enclosingClass.asClass)) diff --git a/src/dotty/tools/dotc/transform/LambdaLift.scala b/src/dotty/tools/dotc/transform/LambdaLift.scala index bffc7458e..41d6f3c43 100644 --- a/src/dotty/tools/dotc/transform/LambdaLift.scala +++ b/src/dotty/tools/dotc/transform/LambdaLift.scala @@ -384,14 +384,23 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform private def addFreeParams(tree: Tree, proxies: List[Symbol])(implicit ctx: Context, info: TransformerInfo): Tree = proxies match { case Nil => tree case proxies => + val sym = tree.symbol val ownProxies = - if (!tree.symbol.isConstructor) proxies - else proxies.map(_.copy(owner = tree.symbol, flags = Synthetic | Param)) + if (!sym.isConstructor) proxies + else proxies.map(_.copy(owner = sym, flags = Synthetic | Param)) 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))) + def copyParams(rhs: Tree) = { + ctx.log(i"copy params ${proxies.map(_.showLocated)}%, %, own = ${ownProxies.map(_.showLocated)}%, %") + seq((proxies, ownProxies).zipped.map(proxyInit), rhs) + } tree match { case tree: DefDef => - cpy.DefDef(tree)(vparamss = tree.vparamss.map(freeParamDefs ++ _)) + cpy.DefDef(tree)( + vparamss = tree.vparamss.map(freeParamDefs ++ _), + rhs = if (sym.isPrimaryConstructor) copyParams(tree.rhs) else tree.rhs) case tree: Template => cpy.Template(tree)(body = freeParamDefs ++ tree.body) } diff --git a/tests/run/i659.scala b/tests/run/i659.scala new file mode 100644 index 000000000..d1229515d --- /dev/null +++ b/tests/run/i659.scala @@ -0,0 +1,26 @@ +class Foo(val a: Int) { + def foo = { {case x => x + a}: PartialFunction[Int, Int]} + class Bar { def result(x: Int) = x + a } + def bar = new Bar +} + +class VFoo(val a: Int) extends AnyVal { + def foo = { {case x => x + a}: PartialFunction[Int, Int]} +} + +object Test extends dotty.runtime.LegacyApp { + + def Foo(a: Int) = { + class Bar { def result(x: Int) = x + a } + new Bar().result(2) + } + + val x1 = new Foo(1).bar.result(2) + assert(x1 == 3, s"x1 = $x1") + val x2 = Foo(1) + assert(x2 == 3, s"x2 = $x2") + val x3 = new Foo(1).foo.apply(2) + assert(x3 == 3, s"x3 = $x3") + val x4 = new VFoo(1).foo.apply(2) + assert(x4 == 3, s"x4 = $x4") +} |