Skip to content

Commit 1ee6352

Browse files
committed
SI-8888 Avoid ClassFormatError under -Ydelambdafy:method
The pattern matcher phase (conceivably, among others) can generate code that binds local `Ident`s symbolically, rather than according to the lexical scope. This means that a lambda can capture more than one local of the same name. In the enclosed test case, this ends up creating the following tree after delambdafy [[syntax trees at end of delambdafy]] // delambday-patmat-path-dep.scala matchEnd4({ case <synthetic> val x1: Object = (x2: Object); case5(){ if (x1.$isInstanceOf[C]()) { <synthetic> val x2#19598: C = (x1.$asInstanceOf[C](): C); matchEnd4({ { (new resume$1(x2#19598, x2#19639): runtime.AbstractFunction0) }; scala.runtime.BoxedUnit.UNIT }) } else case6() }; ... }) ... <synthetic> class resume$1 extends AbstractFunction0 { <synthetic> var x2: C = null; <synthetic> var x2: C = null; ... } After this commit, the var members of `resume$1` are given fresh names, rather than directly using the name of the captured var: <synthetic> var x2$3: C = null; <synthetic> var x2$4: C = null;
1 parent 7b2c3cb commit 1ee6352

File tree

3 files changed

+14
-1
lines changed

3 files changed

+14
-1
lines changed

src/compiler/scala/tools/nsc/transform/Delambdafy.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre
260260

261261
val captureProxies2 = new LinkedHashMap[Symbol, TermSymbol]
262262
captures foreach {capture =>
263-
val sym = lambdaClass.newVariable(capture.name.toTermName, capture.pos, SYNTHETIC)
263+
val sym = lambdaClass.newVariable(unit.freshTermName(capture.name.toString + "$"), capture.pos, SYNTHETIC)
264264
sym setInfo capture.info
265265
captureProxies2 += ((capture, sym))
266266
}

test/files/run/t8888.flags

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-Ydelambdafy:method

test/files/run/t8888.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
class C {
2+
final def resume: Unit = (this: Any) match {
3+
case x : C => (x: Any) match {
4+
case y : C =>
5+
() => (x, y) // used to trigger a ClassFormatError under -Ydelambdafy:method
6+
}
7+
}
8+
}
9+
10+
object Test extends App {
11+
new C().resume
12+
}

0 commit comments

Comments
 (0)