Skip to content

Commit 950ead1

Browse files
committed
Improve tuple specialization code
1 parent c4fb0ac commit 950ead1

File tree

5 files changed

+15
-13
lines changed

5 files changed

+15
-13
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

+1
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,7 @@ class Definitions {
814814
def TupleXXL_fromIterator(implicit ctx: Context): Symbol = TupleXXLModule.requiredMethod("fromIterator")
815815

816816
lazy val DynamicTupleModule: Symbol = ctx.requiredModule("scala.runtime.DynamicTuple")
817+
lazy val DynamicTupleModuleClass: Symbol = DynamicTupleModule.moduleClass
817818
lazy val DynamicTuple_consIterator: Symbol = DynamicTupleModule.requiredMethod("consIterator")
818819
lazy val DynamicTuple_concatIterator: Symbol = DynamicTupleModule.requiredMethod("concatIterator")
819820
lazy val DynamicTuple_dynamicApply: Symbol = DynamicTupleModule.requiredMethod("dynamicApply")

compiler/src/dotty/tools/dotc/transform/TupleOptimizations.scala

+10-9
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ class TupleOptimizations extends MiniPhase with IdentityDenotTransformer {
2424
def phaseName: String = "genericTuples"
2525

2626
override def transformApply(tree: tpd.Apply)(implicit ctx: Context): tpd.Tree = {
27-
if (tree.symbol == defn.DynamicTuple_dynamicCons) transformTupleCons(tree)
27+
if (!tree.symbol.exists || tree.symbol.owner != defn.DynamicTupleModuleClass) super.transformApply(tree)
28+
else if (tree.symbol == defn.DynamicTuple_dynamicCons) transformTupleCons(tree)
2829
else if (tree.symbol == defn.DynamicTuple_dynamicTail) transformTupleTail(tree)
2930
else if (tree.symbol == defn.DynamicTuple_dynamicSize) transformTupleSize(tree)
3031
else if (tree.symbol == defn.DynamicTuple_dynamicConcat) transformTupleConcat(tree)
@@ -34,8 +35,7 @@ class TupleOptimizations extends MiniPhase with IdentityDenotTransformer {
3435
}
3536

3637
private def transformTupleCons(tree: tpd.Apply)(implicit ctx: Context): Tree = {
37-
val TypeApply(_, headType :: tailType :: Nil) = tree.fun
38-
val tail :: head :: Nil = tree.args
38+
val head :: tail :: Nil = tree.args
3939
tupleTypes(tree.tpe) match {
4040
case Some(tpes) =>
4141
// Generate a the tuple directly with TupleN+1.apply
@@ -44,7 +44,7 @@ class TupleOptimizations extends MiniPhase with IdentityDenotTransformer {
4444
// val t = tail
4545
// TupleN+1(head, t._1, ..., t._n)
4646
evalOnce(Typed(tail, TypeTree(defn.tupleType(tpes.tail)))) { tup =>
47-
val elements = head :: (0 until size - 1).map(i => tup.select(nme.selectorName(i))).toList
47+
val elements = head :: tupleSelectors(tup, size - 1)
4848
knownTupleFromElements(tpes, elements)
4949
}
5050
} else {
@@ -77,7 +77,7 @@ class TupleOptimizations extends MiniPhase with IdentityDenotTransformer {
7777
// val t = tup.asInstanceOf[TupleN[...]]
7878
// TupleN-1(t._2, ..., t._n)
7979
evalOnce(Typed(tup, TypeTree(defn.tupleType(tpes)))) { tup =>
80-
val elements = (1 until size).map(i => tup.select(nme.selectorName(i))).toList
80+
val elements = tupleSelectors(tup, size).tail
8181
knownTupleFromElements(tpes.tail, elements)
8282
}
8383
} else if (size <= MaxTupleArity + 1) {
@@ -125,10 +125,7 @@ class TupleOptimizations extends MiniPhase with IdentityDenotTransformer {
125125
evalOnce(Typed(self, TypeTree(defn.tupleType(tpes1)))) { self =>
126126
evalOnce(Typed(that, TypeTree(defn.tupleType(tpes2)))) { that =>
127127
val types = tpes1 ::: tpes2
128-
val elements = {
129-
(0 until n).map(i => self.select(nme.selectorName(i))) ++
130-
(0 until m).map(i => that.select(nme.selectorName(i)))
131-
}.toList
128+
val elements = tupleSelectors(self, n) ::: tupleSelectors(that, m)
132129
knownTupleFromElements(types, elements)
133130
}
134131
}
@@ -235,4 +232,8 @@ class TupleOptimizations extends MiniPhase with IdentityDenotTransformer {
235232
}
236233
rec(tp.stripTypeVar, Nil, bound)
237234
}
235+
236+
private def tupleSelectors(tup: Tree, size: Int)(implicit ctx: Context): List[Tree] =
237+
(0 until size).map(i => tup.select(nme.selectorName(i))).toList
238+
238239
}

library/src-3.x/scala/Tuple.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ sealed trait Tuple extends Any {
1717
* This opteration is O(this.size)
1818
*/
1919
inline def *: [H, This >: this.type <: Tuple] (x: H): H *: This =
20-
DynamicTuple.dynamicCons[This, H](this, x)
20+
DynamicTuple.dynamicCons[H, This](x, this)
2121

2222
/** Return a new tuple by concatenating `this` tuple with `that` tuple.
2323
* This opteration is O(this.size + that.size)

library/src-3.x/scala/runtime/DynamicTuple.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ object DynamicTuple {
186186
arr
187187
}
188188

189-
def dynamicCons[This <: Tuple, H] (self: Tuple, x: H): H *: This = {
189+
def dynamicCons[H, This <: Tuple](x: H, self: Tuple): H *: This = {
190190
type Result = H *: This
191191
(self: Any) match {
192192
case () =>

tests/run-with-compiler/staged-tuples/StagedTuple.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ object StagedTuple {
184184
}
185185

186186
def consStaged[T <: Tuple & Singleton : Type, H : Type](self: Expr[T], x: Expr[H], tailSize: Option[Int]): Expr[H *: T] =
187-
if (!specialize) '{dynamicCons[T, H]($self, $x)}
187+
if (!specialize) '{dynamicCons[H, T]($x, $self)}
188188
else {
189189
val res = tailSize match {
190190
case Some(0) =>
@@ -200,7 +200,7 @@ object StagedTuple {
200200
case Some(n) =>
201201
fromArrayStaged[H *: T]('{cons$Array($x, ${ toArrayStaged(self, tailSize) })}, Some(n + 1))
202202
case _ =>
203-
'{dynamicCons[T, H]($self, $x)}
203+
'{dynamicCons[H, T]($x, $self)}
204204
}
205205
res.as[H *: T]
206206
}

0 commit comments

Comments
 (0)