Skip to content

Commit 518b92d

Browse files
committed
Fix #2004: Add forwarders to XXL functions apply method
1 parent abad0ad commit 518b92d

File tree

6 files changed

+99
-3
lines changed

6 files changed

+99
-3
lines changed

compiler/src/dotty/tools/dotc/Compiler.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ class Compiler {
7575
new AugmentScala2Traits, // Expand traits defined in Scala 2.11 to simulate old-style rewritings
7676
new ResolveSuper, // Implement super accessors and add forwarders to trait methods
7777
new PrimitiveForwarders, // Add forwarders to trait methods that have a mismatch between generic and primitives
78+
new FunctionXXLForwarders, // Add forwarders for FunctionXXL apply method
7879
new ArrayConstructors), // Intercept creation of (non-generic) arrays and intrinsify.
7980
List(new Erasure), // Rewrite types to JVM model, erasing all type parameters, abstract types and refinements.
8081
List(new ElimErasedValueType, // Expand erased value types to their underlying implmementation types
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package dotty.tools.dotc
2+
package transform
3+
4+
import core._
5+
import Constants.Constant
6+
import Contexts.Context
7+
import Flags._
8+
import Definitions._
9+
import DenotTransformers._
10+
import StdNames._
11+
import Symbols._
12+
import TreeTransforms._
13+
import Types._
14+
15+
16+
/** This phase adds forwarder for XXL functions `apply` methods that are implemented with a method
17+
* with explicit parameters (not in Array[Object]).
18+
*
19+
* In particular for every method
20+
* `def apply(x1: T1, ... xn: Tn): R` in class `M` subtype of `FunctionN[T1, ..., Tn, R]` with `N` > 22
21+
* a forwarder
22+
* `def apply(xs: Array[Object]): R = this.apply(xs(0).asInstanceOf[T1], ..., xs(n-1).asInstanceOf[Tn]).asInstanceOf[R]`
23+
* is generated.
24+
*/
25+
class FunctionXXLForwarders extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform =>
26+
import ast.tpd._
27+
28+
override def phaseName: String = "functionXXLForwarders"
29+
30+
override def transformTemplate(impl: Template)(implicit ctx: Context, info: TransformerInfo): Template = {
31+
32+
def forwarderRhs(receiver: Tree, xsTree: Tree): Tree = {
33+
val argsApply = ref(xsTree.symbol).select(nme.apply)
34+
var idx = -1
35+
val argss = receiver.tpe.widenDealias.paramInfoss.map(_.map { param =>
36+
idx += 1
37+
argsApply.appliedToArgs(List(Literal(Constant(idx)))).asInstance(param)
38+
})
39+
ref(receiver.symbol).appliedToArgss(argss).asInstance(defn.ObjectType)
40+
}
41+
42+
val forwarders =
43+
for {
44+
tree <- if (impl.symbol.owner.is(Trait)) Nil else impl.body
45+
if tree.symbol.is(Method) && tree.symbol.name == nme.apply &&
46+
tree.symbol.signature.paramsSig.size > MaxImplementedFunctionArity &&
47+
tree.symbol.allOverriddenSymbols.exists(sym => defn.isXXLFunctionClass(sym.owner))
48+
} yield {
49+
val xsType = defn.ArrayType.appliedTo(List(defn.ObjectType))
50+
val methType = MethodType(List(nme.args))(_ => List(xsType), _ => defn.ObjectType)
51+
val meth = ctx.newSymbol(tree.symbol.owner, nme.apply, Synthetic | Method, methType)
52+
DefDef(meth, paramss => forwarderRhs(tree, paramss.head.head))
53+
}
54+
55+
cpy.Template(impl)(body = forwarders ::: impl.body)
56+
}
57+
58+
}

tests/run/i2004.check

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
1
1+
2
2+
67

tests/run/i2004.scala

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
object Test {
22
def main(args: Array[String]) = {
3-
val f: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int,Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int =
3+
4+
val f: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int,Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int = new Fun26
5+
println(f.apply(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1))
6+
7+
val g: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int,Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int =
48
{
59
(x1: Int, x2: Int, x3: Int, x4: Int, x5: Int, x6: Int, x7: Int, x8: Int, x9: Int, x10: Int, x11: Int, x12: Int, x13: Int, x14: Int, x15: Int, x16: Int, x17: Int, x18: Int, x19: Int, x20: Int, x21: Int, x22: Int, x23: Int, x24: Int, x25: Int, x26: Int) =>
610
x1
711
}
8-
println(f.apply(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1))
12+
println(g.apply(67, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1))
913

1014
}
1115
}
16+
17+
class Fun26 extends Function26[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int,Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int] {
18+
def apply(x1: Int, x2: Int, x3: Int, x4: Int, x5: Int, x6: Int, x7: Int, x8: Int, x9: Int, x10: Int, x11: Int, x12: Int, x13: Int, x14: Int, x15: Int, x16: Int, x17: Int, x18: Int, x19: Int, x20: Int, x21: Int, x22: Int, x23: Int, x24: Int, x25: Int, x26: Int): Int = x2
19+
}

tests/run/i2004b.check

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
4
2+
3

tests/run/i2004b.scala

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
object Test {
2+
def main(args: Array[String]) = {
3+
val f: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int,Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int = new Fun26_1
4+
println(f.apply(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1))
5+
6+
val g: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int,Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int = new Fun26_2
7+
println(g.apply(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1))
8+
}
9+
}
10+
11+
12+
class Fun26_1 extends Fun26_t {
13+
override def apply(x1: Int, x2: Int, x3: Int, x4: Int, x5: Int, x6: Int, x7: Int, x8: Int, x9: Int, x10: Int, x11: Int, x12: Int, x13: Int, x14: Int, x15: Int, x16: Int, x17: Int, x18: Int, x19: Int, x20: Int, x21: Int, x22: Int, x23: Int, x24: Int, x25: Int, x26: Int): Int = x4
14+
}
15+
16+
class Fun26_2 extends Fun26_c {
17+
override def apply(x1: Int, x2: Int, x3: Int, x4: Int, x5: Int, x6: Int, x7: Int, x8: Int, x9: Int, x10: Int, x11: Int, x12: Int, x13: Int, x14: Int, x15: Int, x16: Int, x17: Int, x18: Int, x19: Int, x20: Int, x21: Int, x22: Int, x23: Int, x24: Int, x25: Int, x26: Int): Int = x3
18+
}
19+
20+
trait Fun26_t extends Function26[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int,Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int] {
21+
def apply(x1: Int, x2: Int, x3: Int, x4: Int, x5: Int, x6: Int, x7: Int, x8: Int, x9: Int, x10: Int, x11: Int, x12: Int, x13: Int, x14: Int, x15: Int, x16: Int, x17: Int, x18: Int, x19: Int, x20: Int, x21: Int, x22: Int, x23: Int, x24: Int, x25: Int, x26: Int): Int = x2
22+
}
23+
24+
trait Fun26_c extends Function26[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int,Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int] {
25+
def apply(x1: Int, x2: Int, x3: Int, x4: Int, x5: Int, x6: Int, x7: Int, x8: Int, x9: Int, x10: Int, x11: Int, x12: Int, x13: Int, x14: Int, x15: Int, x16: Int, x17: Int, x18: Int, x19: Int, x20: Int, x21: Int, x22: Int, x23: Int, x24: Int, x25: Int, x26: Int): Int = x2
26+
}

0 commit comments

Comments
 (0)