Skip to content

Commit 029cce7

Browse files
committed
Merge pull request scala#4367 from retronym/topic/indylambda-specialization
Disable -Ydelambdafy:method for specialized FunctionN
2 parents 8623c2b + ea61b3f commit 029cce7

12 files changed

+76
-37
lines changed

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

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,14 @@ abstract class UnCurry extends InfoTransform
7171
private val noApply = mutable.HashSet[Tree]()
7272
private val newMembers = mutable.Map[Symbol, mutable.Buffer[Tree]]()
7373

74+
private lazy val forceSpecializationInfoTransformOfFunctionN: Unit = {
75+
if (currentRun.specializePhase != NoPhase) { // be robust in case of -Ystop-after:uncurry
76+
exitingSpecialize {
77+
FunctionClass.seq.foreach(cls => cls.info)
78+
}
79+
}
80+
}
81+
7482
/** Add a new synthetic member for `currentOwner` */
7583
private def addNewMember(t: Tree): Unit =
7684
newMembers.getOrElseUpdate(currentOwner, mutable.Buffer()) += t
@@ -221,8 +229,16 @@ abstract class UnCurry extends InfoTransform
221229
def mkMethod(owner: Symbol, name: TermName, additionalFlags: FlagSet = NoFlags): DefDef =
222230
gen.mkMethodFromFunction(localTyper)(fun, owner, name, additionalFlags)
223231

224-
val canUseDelamdafyMethod = (inConstructorFlag == 0) // Avoiding synthesizing code prone to SI-6666, SI-8363 by using old-style lambda translation
232+
def isSpecialized = {
233+
forceSpecializationInfoTransformOfFunctionN
234+
val specialized = specializeTypes.specializedType(fun.tpe)
235+
!(specialized =:= fun.tpe)
236+
}
225237

238+
def canUseDelamdafyMethod = (
239+
(inConstructorFlag == 0) // Avoiding synthesizing code prone to SI-6666, SI-8363 by using old-style lambda translation
240+
&& !isSpecialized // DelambdafyTransformer currently only emits generic FunctionN-s, use the old style in the meantime
241+
)
226242
if (inlineFunctionExpansion || !canUseDelamdafyMethod) {
227243
val parents = addSerializable(abstractFunctionForFunctionType(fun.tpe))
228244
val anonClass = fun.symbol.owner newAnonymousFunctionClass(fun.pos, inConstructorFlag) addAnnotation SerialVersionUIDAnnotation
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
scala.runtime.AbstractFunction1$mcII$sp
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-Ydelambdafy:method
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
object Test {
2+
def main(args: Array[String]): Unit = {
3+
val f = (x: Int) => -x
4+
println(f.getClass.getSuperclass.getName)
5+
}
6+
}

test/files/run/delambdafy_t6028.check

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,35 @@
11
[[syntax trees at end of lambdalift]] // newSource1.scala
22
package <empty> {
33
class T extends Object {
4-
<paramaccessor> private[this] val classParam: Int = _;
5-
def <init>(classParam: Int): T = {
4+
<paramaccessor> private[this] val classParam: String = _;
5+
def <init>(classParam: String): T = {
66
T.super.<init>();
77
()
88
};
9-
private[this] val field: Int = 0;
10-
<stable> <accessor> def field(): Int = T.this.field;
11-
def foo(methodParam: Int): Function0 = {
12-
val methodLocal: Int = 0;
9+
private[this] val field: String = "";
10+
<stable> <accessor> def field(): String = T.this.field;
11+
def foo(methodParam: String): Function0 = {
12+
val methodLocal: String = "";
1313
{
1414
(() => T.this.$anonfun$1(methodParam, methodLocal)).$asInstanceOf[Function0]()
1515
}
1616
};
17-
def bar(barParam: Int): Object = {
17+
def bar(barParam: String): Object = {
1818
@volatile var MethodLocalObject$module: runtime.VolatileObjectRef = scala.runtime.VolatileObjectRef.zero();
1919
T.this.MethodLocalObject$1(barParam, MethodLocalObject$module)
2020
};
21-
def tryy(tryyParam: Int): Function0 = {
22-
var tryyLocal: runtime.IntRef = scala.runtime.IntRef.create(0);
21+
def tryy(tryyParam: String): Function0 = {
22+
var tryyLocal: runtime.ObjectRef = scala.runtime.ObjectRef.create("");
2323
{
24-
(() => T.this.$anonfun$2(tryyParam, tryyLocal)).$asInstanceOf[Function0]()
24+
(new <$anon: Function0>(T.this, tryyParam, tryyLocal): Function0)
2525
}
2626
};
27-
final <artifact> private[this] def $anonfun$1(methodParam$1: Int, methodLocal$1: Int): Int = T.this.classParam.+(T.this.field()).+(methodParam$1).+(methodLocal$1);
27+
final <artifact> private[this] def $anonfun$1(methodParam$1: String, methodLocal$1: String): String = T.this.classParam.+(T.this.field()).+(methodParam$1).+(methodLocal$1);
2828
abstract trait MethodLocalTrait$1 extends Object {
2929
<synthetic> <stable> <artifact> def $outer(): T
3030
};
3131
object MethodLocalObject$2 extends Object with T#MethodLocalTrait$1 {
32-
def <init>($outer: T, barParam$1: Int): T#MethodLocalObject$2.type = {
32+
def <init>($outer: T, barParam$1: String): T#MethodLocalObject$2.type = {
3333
MethodLocalObject$2.super.<init>();
3434
MethodLocalObject$2.this.$asInstanceOf[T#MethodLocalTrait$1$class]()./*MethodLocalTrait$1$class*/$init$(barParam$1);
3535
()
@@ -38,19 +38,34 @@ package <empty> {
3838
<synthetic> <stable> <artifact> def $outer(): T = MethodLocalObject$2.this.$outer;
3939
<synthetic> <stable> <artifact> def $outer(): T = MethodLocalObject$2.this.$outer
4040
};
41-
final <stable> private[this] def MethodLocalObject$1(barParam$1: Int, MethodLocalObject$module$1: runtime.VolatileObjectRef): T#MethodLocalObject$2.type = {
41+
final <stable> private[this] def MethodLocalObject$1(barParam$1: String, MethodLocalObject$module$1: runtime.VolatileObjectRef): T#MethodLocalObject$2.type = {
4242
MethodLocalObject$module$1.elem = new T#MethodLocalObject$2.type(T.this, barParam$1);
4343
MethodLocalObject$module$1.elem.$asInstanceOf[T#MethodLocalObject$2.type]()
4444
};
4545
abstract trait MethodLocalTrait$1$class extends Object with T#MethodLocalTrait$1 {
46-
def /*MethodLocalTrait$1$class*/$init$(barParam$1: Int): Unit = {
46+
def /*MethodLocalTrait$1$class*/$init$(barParam$1: String): Unit = {
4747
()
4848
};
49-
scala.this.Predef.print(scala.Int.box(barParam$1))
49+
scala.this.Predef.print(barParam$1)
5050
};
51-
final <artifact> private[this] def $anonfun$2(tryyParam$1: Int, tryyLocal$1: runtime.IntRef): Unit = try {
52-
tryyLocal$1.elem = tryyParam$1
53-
} finally ()
51+
@SerialVersionUID(value = 0) final <synthetic> class $anonfun$tryy$1 extends scala.runtime.AbstractFunction0$mcV$sp with Serializable {
52+
def <init>($outer: T, tryyParam$1: String, tryyLocal$1: runtime.ObjectRef): <$anon: Function0> = {
53+
$anonfun$tryy$1.super.<init>();
54+
()
55+
};
56+
final def apply(): Unit = $anonfun$tryy$1.this.apply$mcV$sp();
57+
<specialized> def apply$mcV$sp(): Unit = try {
58+
$anonfun$tryy$1.this.tryyLocal$1.elem = $anonfun$tryy$1.this.tryyParam$1
59+
} finally ();
60+
<synthetic> <paramaccessor> <artifact> private[this] val $outer: T = _;
61+
<synthetic> <stable> <artifact> def $outer(): T = $anonfun$tryy$1.this.$outer;
62+
final <bridge> <artifact> def apply(): Object = {
63+
$anonfun$tryy$1.this.apply();
64+
scala.runtime.BoxedUnit.UNIT
65+
};
66+
<synthetic> <paramaccessor> private[this] val tryyParam$1: String = _;
67+
<synthetic> <paramaccessor> private[this] val tryyLocal$1: runtime.ObjectRef = _
68+
}
5469
}
5570
}
5671

test/files/run/delambdafy_t6028.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ object Test extends DirectTest {
55

66
override def extraSettings: String = "-usejavacp -Ydelambdafy:method -Xprint:lambdalift -d " + testOutput.path
77

8-
override def code = """class T(classParam: Int) {
9-
| val field: Int = 0
10-
| def foo(methodParam: Int) = {val methodLocal = 0 ; () => classParam + field + methodParam + methodLocal }
11-
| def bar(barParam: Int) = { trait MethodLocalTrait { print(barParam) }; object MethodLocalObject extends MethodLocalTrait; MethodLocalObject }
12-
| def tryy(tryyParam: Int) = { var tryyLocal = 0; () => try { tryyLocal = tryyParam } finally () }
8+
override def code = """class T(classParam: String) {
9+
| val field: String = ""
10+
| def foo(methodParam: String) = {val methodLocal = "" ; () => classParam + field + methodParam + methodLocal }
11+
| def bar(barParam: String) = { trait MethodLocalTrait { print(barParam) }; object MethodLocalObject extends MethodLocalTrait; MethodLocalObject }
12+
| def tryy(tryyParam: String) = { var tryyLocal = ""; () => try { tryyLocal = tryyParam } finally () }
1313
|}
1414
|""".stripMargin.trim
1515

test/files/run/delambdafy_t6555.check

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ package <empty> {
55
Foo.super.<init>();
66
()
77
};
8-
private[this] val f: Int => Int = {
9-
final <artifact> def $anonfun(param: Int): Int = param;
10-
((param: Int) => $anonfun(param))
8+
private[this] val f: String => String = {
9+
final <artifact> def $anonfun(param: String): String = param;
10+
((param: String) => $anonfun(param))
1111
};
12-
<stable> <accessor> def f(): Int => Int = Foo.this.f
12+
<stable> <accessor> def f(): String => String = Foo.this.f
1313
}
1414
}
1515

test/files/run/delambdafy_t6555.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ object Test extends DirectTest {
55

66
override def extraSettings: String = "-usejavacp -Xprint:specialize -Ydelambdafy:method -d " + testOutput.path
77

8-
override def code = "class Foo { val f = (param: Int) => param } "
8+
override def code = "class Foo { val f = (param: String) => param } "
99

1010
override def show(): Unit = {
1111
Console.withErr(System.out) {

test/files/run/delambdafy_uncurry_byname_method.check

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ package <empty> {
55
Foo.super.<init>();
66
()
77
};
8-
def bar(x: () => Int): Int = x.apply();
9-
def foo(): Int = Foo.this.bar({
10-
final <artifact> def $anonfun(): Int = 1;
8+
def bar(x: () => String): String = x.apply();
9+
def foo(): String = Foo.this.bar({
10+
final <artifact> def $anonfun(): String = "";
1111
(() => $anonfun())
1212
})
1313
}

test/files/run/delambdafy_uncurry_byname_method.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ object Test extends DirectTest {
66
override def extraSettings: String = "-usejavacp -Xprint:uncurry -Ydelambdafy:method -Ystop-after:uncurry -d " + testOutput.path
77

88
override def code = """class Foo {
9-
| def bar(x: => Int) = x
9+
| def bar(x: => String) = x
1010
|
11-
| def foo = bar(1)
11+
| def foo = bar("")
1212
|}
1313
|""".stripMargin.trim
1414

0 commit comments

Comments
 (0)