Skip to content

Commit b6ea4cd

Browse files
committed
Make sure to copy local symbols when reducing projections
If the result of reducing a projection has local bindings, these bindings need to be copied. Test case in run/Tuple.scala
1 parent 5df5552 commit b6ea4cd

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

compiler/src/dotty/tools/dotc/typer/Inliner.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -469,10 +469,13 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
469469
val argInPlace =
470470
if (trailing.isEmpty) arg
471471
else letBindUnless(TreeInfo.Pure, arg)(seq(trailing, _))
472-
seq(prefix, seq(leading, argInPlace))
473-
.reporting(res => i"projecting $tree -> $res", inlining)
472+
val fullArg = seq(prefix, seq(leading, argInPlace))
473+
new TreeTypeMap().transform(fullArg) // make sure local bindings in argument have fresh symbols
474+
.reporting(res => i"projecting $tree -> $res")
474475
}
475476
else tree
477+
case Block(stats, expr) if stats.forall(isPureBinding) =>
478+
cpy.Block(tree)(stats, reduceProjection(expr))
476479
case _ => tree
477480
}
478481
}

tests/run/Tuple.scala

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import annotation.showAsInfix
2+
3+
sealed trait Tuple
4+
5+
object Tuple {
6+
object Empty extends Tuple
7+
8+
type Empty = Empty.type
9+
10+
@showAsInfix
11+
final case class *: [H, T <: Tuple](hd: H, tl: T) extends Tuple
12+
13+
class HListDeco(val xs: Tuple) extends AnyVal {
14+
transparent def *: [H] (x: H): Tuple = Tuple.*:.apply(x, xs)
15+
16+
transparent def size: Int = Tuple.size(xs)
17+
}
18+
19+
transparent def size(xs: Tuple): Int = xs match {
20+
case Empty => 0
21+
case _ *: xs1 => size(xs1) + 1
22+
}
23+
24+
transparent implicit def hlistDeco(xs: Tuple): HListDeco = new HListDeco(xs)
25+
26+
transparent def apply(): Tuple = Empty
27+
transparent def apply(x1: Any): Tuple = x1 *: Empty
28+
transparent def apply(x1: Any, x2: Any) = x1 *: x2 *: Empty
29+
30+
val xs0 = Tuple()
31+
val xs1 = Tuple(2)
32+
val xs2 = Tuple(2, "a")
33+
val s0 = xs0.size
34+
val s1 = xs1.size
35+
val s2 = xs2.size
36+
}
37+
38+
object Test extends App

0 commit comments

Comments
 (0)