@@ -64,7 +64,7 @@ class TuplesOptimizations extends MiniPhase with IdentityDenotTransformer {
64
64
65
65
private def transformTupleTail (tree : tpd.Apply )(implicit ctx : Context ): Tree = {
66
66
val Apply (TypeApply (_, tpt :: Nil ), tup :: Nil ) = tree
67
- tupleTypes(tpt.tpe) match { // TODO tupleBoundedTypes
67
+ tupleTypes(tpt.tpe, MaxTupleArity + 1 ) match {
68
68
case Some (tpes) =>
69
69
// Generate a the tuple directly with TupleN-1.apply
70
70
val size = tpes.size
@@ -154,7 +154,7 @@ class TuplesOptimizations extends MiniPhase with IdentityDenotTransformer {
154
154
if (n < 0 || n >= size) {
155
155
ctx.error(" index out of bounds: " + n, nTree.underlyingArgument.sourcePos)
156
156
tree
157
- } else if (size <= Definitions . MaxTupleArity ) {
157
+ } else if (size <= MaxTupleArity ) {
158
158
// tup._n
159
159
Typed (tup, TypeTree (defn.tupleType(tpes))).select(nme.selectorName(n))
160
160
} else {
@@ -173,13 +173,13 @@ class TuplesOptimizations extends MiniPhase with IdentityDenotTransformer {
173
173
174
174
private def transformTupleToArray (tree : tpd.Apply )(implicit ctx : Context ): Tree = {
175
175
val Apply (_, tup :: Nil ) = tree
176
- tupleTypes(tup.tpe.widen) match { // TODO tupleBoundedTypes
176
+ tupleTypes(tup.tpe.widen, MaxTupleArity ) match {
177
177
case Some (tpes) =>
178
178
val size = tpes.size
179
179
if (size == 0 ) {
180
180
// Array.emptyObjectArray
181
181
ref(defn.ArrayModule .companionModule).select(" emptyObjectArray" .toTermName).ensureApplied
182
- } else if (size <= Definitions . MaxTupleArity ) {
182
+ } else if (size <= MaxTupleArity ) {
183
183
// DynamicTuple.productToArray(tup.asInstanceOf[Product])
184
184
ref(defn.DynamicTuple_productToArray ).appliedTo(tup.asInstance(defn.ProductType ))
185
185
} else {
@@ -196,7 +196,7 @@ class TuplesOptimizations extends MiniPhase with IdentityDenotTransformer {
196
196
/** Create a TupleN (1 <= N < 23) from the elements */
197
197
private def knownTupleFromElements (tpes : List [Type ], elements : List [Tree ])(implicit ctx : Context ) = {
198
198
val size = elements.size
199
- assert(0 < size && size <= Definitions . MaxTupleArity )
199
+ assert(0 < size && size <= MaxTupleArity )
200
200
val tupleModule = defn.TupleType (size).classSymbol.companionModule
201
201
ref(tupleModule).select(nme.apply).appliedToTypes(tpes).appliedToArgs(elements)
202
202
}
@@ -206,7 +206,7 @@ class TuplesOptimizations extends MiniPhase with IdentityDenotTransformer {
206
206
// Unit for empty tuple
207
207
Literal (Constant (())) // TODO should this code be here? Or assert(size > specializedSize)
208
208
}
209
- else if (size <= Definitions . MaxTupleArity ) {
209
+ else if (size <= MaxTupleArity ) {
210
210
// TupleN(it.next(), ..., it.next())
211
211
212
212
// TODO outline this code for the 22 alternatives (or less, may not need the smallest ones)?
@@ -222,13 +222,14 @@ class TuplesOptimizations extends MiniPhase with IdentityDenotTransformer {
222
222
}
223
223
}
224
224
225
- private def tupleTypes (tp : Type )(implicit ctx : Context ): Option [List [Type ]] = {
226
- @ tailrec def rec (tp : Type , acc : List [Type ]): Option [List [Type ]] = tp match {
227
- case tp : AppliedType if defn.PairClass == tp.classSymbol => rec(tp.args(1 ), tp.args(0 ) :: acc)
225
+ private def tupleTypes (tp : Type , bound : Int = Int .MaxValue )(implicit ctx : Context ): Option [List [Type ]] = {
226
+ @ tailrec def rec (tp : Type , acc : List [Type ], bound : Int ): Option [List [Type ]] = tp match {
227
+ case _ if bound < 0 => Some (acc.reverse)
228
+ case tp : AppliedType if defn.PairClass == tp.classSymbol => rec(tp.args(1 ), tp.args.head :: acc, bound - 1 )
228
229
case tp : AppliedType if defn.isTupleClass(tp.tycon.classSymbol) => Some (acc.reverse ::: tp.args)
229
230
case tp if tp.classSymbol == defn.UnitClass => Some (acc.reverse)
230
231
case _ => None
231
232
}
232
- rec(tp.stripTypeVar, Nil )
233
+ rec(tp.stripTypeVar, Nil , bound )
233
234
}
234
235
}
0 commit comments