Skip to content

Commit ad6c4ad

Browse files
committed
Merge pull request #671 from dotty-staging/fix/#659-lambdalift-proxies
Fix/#659 lambdalift proxies
2 parents c54debe + 25304a0 commit ad6c4ad

File tree

4 files changed

+49
-7
lines changed

4 files changed

+49
-7
lines changed

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,13 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
7676
def Block(stats: List[Tree], expr: Tree)(implicit ctx: Context): Block =
7777
ta.assignType(untpd.Block(stats, expr), stats, expr)
7878

79-
def maybeBlock(stats: List[Tree], expr: Tree)(implicit ctx: Context): Tree =
80-
if (stats.isEmpty) expr else Block(stats, expr)
79+
/** Join `stats` in front of `expr` creating a new block if necessary */
80+
def seq(stats: List[Tree], expr: Tree)(implicit ctx: Context): Tree =
81+
if (stats.isEmpty) expr
82+
else expr match {
83+
case Block(estats, eexpr) => cpy.Block(expr)(stats ::: estats, eexpr)
84+
case _ => Block(stats, expr)
85+
}
8186

8287
def If(cond: Tree, thenp: Tree, elsep: Tree)(implicit ctx: Context): If =
8388
ta.assignType(untpd.If(cond, thenp, elsep), thenp, elsep)

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,9 @@ object ExplicitOuter {
136136

137137
/** A new outer accessor or param accessor */
138138
private def newOuterSym(owner: ClassSymbol, cls: ClassSymbol, name: TermName, flags: FlagSet)(implicit ctx: Context) = {
139-
ctx.newSymbol(owner, name, Synthetic | flags, cls.owner.enclosingClass.typeRef, coord = cls.coord)
139+
val target = cls.owner.enclosingClass.typeRef
140+
val info = if (flags.is(Method)) ExprType(target) else target
141+
ctx.newSymbol(owner, name, Synthetic | flags, info, coord = cls.coord)
140142
}
141143

142144
/** A new param accessor for the outer field in class `cls` */
@@ -302,7 +304,7 @@ object ExplicitOuter {
302304
val outerAccessorCtx = ctx.withPhaseNoLater(ctx.lambdaLiftPhase) // lambdalift mangles local class names, which means we cannot reliably find outer acessors anymore
303305
ctx.log(i"outer to $toCls of $tree: ${tree.tpe}, looking for ${outerAccName(treeCls.asClass)(outerAccessorCtx)} in $treeCls")
304306
if (treeCls == toCls) tree
305-
else loop(tree select outerAccessor(treeCls.asClass)(outerAccessorCtx))
307+
else loop(tree.select(outerAccessor(treeCls.asClass)(outerAccessorCtx)).ensureApplied)
306308
}
307309
ctx.log(i"computing outerpath to $toCls from ${ctx.outersIterator.map(_.owner).toList}")
308310
loop(This(ctx.owner.enclosingClass.asClass))

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -384,14 +384,23 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform
384384
private def addFreeParams(tree: Tree, proxies: List[Symbol])(implicit ctx: Context, info: TransformerInfo): Tree = proxies match {
385385
case Nil => tree
386386
case proxies =>
387+
val sym = tree.symbol
387388
val ownProxies =
388-
if (!tree.symbol.isConstructor) proxies
389-
else proxies.map(_.copy(owner = tree.symbol, flags = Synthetic | Param))
389+
if (!sym.isConstructor) proxies
390+
else proxies.map(_.copy(owner = sym, flags = Synthetic | Param))
390391
val freeParamDefs = ownProxies.map(proxy =>
391392
transformFollowingDeep(ValDef(proxy.asTerm).withPos(tree.pos)).asInstanceOf[ValDef])
393+
def proxyInit(field: Symbol, param: Symbol) =
394+
transformFollowingDeep(ref(field).becomes(ref(param)))
395+
def copyParams(rhs: Tree) = {
396+
ctx.log(i"copy params ${proxies.map(_.showLocated)}%, %, own = ${ownProxies.map(_.showLocated)}%, %")
397+
seq((proxies, ownProxies).zipped.map(proxyInit), rhs)
398+
}
392399
tree match {
393400
case tree: DefDef =>
394-
cpy.DefDef(tree)(vparamss = tree.vparamss.map(freeParamDefs ++ _))
401+
cpy.DefDef(tree)(
402+
vparamss = tree.vparamss.map(freeParamDefs ++ _),
403+
rhs = if (sym.isPrimaryConstructor) copyParams(tree.rhs) else tree.rhs)
395404
case tree: Template =>
396405
cpy.Template(tree)(body = freeParamDefs ++ tree.body)
397406
}

tests/run/i659.scala

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
class Foo(val a: Int) {
2+
def foo = { {case x => x + a}: PartialFunction[Int, Int]}
3+
class Bar { def result(x: Int) = x + a }
4+
def bar = new Bar
5+
}
6+
7+
class VFoo(val a: Int) extends AnyVal {
8+
def foo = { {case x => x + a}: PartialFunction[Int, Int]}
9+
}
10+
11+
object Test extends dotty.runtime.LegacyApp {
12+
13+
def Foo(a: Int) = {
14+
class Bar { def result(x: Int) = x + a }
15+
new Bar().result(2)
16+
}
17+
18+
val x1 = new Foo(1).bar.result(2)
19+
assert(x1 == 3, s"x1 = $x1")
20+
val x2 = Foo(1)
21+
assert(x2 == 3, s"x2 = $x2")
22+
val x3 = new Foo(1).foo.apply(2)
23+
assert(x3 == 3, s"x3 = $x3")
24+
val x4 = new VFoo(1).foo.apply(2)
25+
assert(x4 == 3, s"x4 = $x4")
26+
}

0 commit comments

Comments
 (0)