@@ -64,7 +64,7 @@ class TuplesOptimizations extends MiniPhase with IdentityDenotTransformer {
6464
6565 private def transformTupleTail (tree : tpd.Apply )(implicit ctx : Context ): Tree = {
6666 val Apply (TypeApply (_, tpt :: Nil ), tup :: Nil ) = tree
67- tupleTypes(tpt.tpe) match { // TODO tupleBoundedTypes
67+ tupleTypes(tpt.tpe, MaxTupleArity + 1 ) match {
6868 case Some (tpes) =>
6969 // Generate a the tuple directly with TupleN-1.apply
7070 val size = tpes.size
@@ -154,7 +154,7 @@ class TuplesOptimizations extends MiniPhase with IdentityDenotTransformer {
154154 if (n < 0 || n >= size) {
155155 ctx.error(" index out of bounds: " + n, nTree.underlyingArgument.sourcePos)
156156 tree
157- } else if (size <= Definitions . MaxTupleArity ) {
157+ } else if (size <= MaxTupleArity ) {
158158 // tup._n
159159 Typed (tup, TypeTree (defn.tupleType(tpes))).select(nme.selectorName(n))
160160 } else {
@@ -173,13 +173,13 @@ class TuplesOptimizations extends MiniPhase with IdentityDenotTransformer {
173173
174174 private def transformTupleToArray (tree : tpd.Apply )(implicit ctx : Context ): Tree = {
175175 val Apply (_, tup :: Nil ) = tree
176- tupleTypes(tup.tpe.widen) match { // TODO tupleBoundedTypes
176+ tupleTypes(tup.tpe.widen, MaxTupleArity ) match {
177177 case Some (tpes) =>
178178 val size = tpes.size
179179 if (size == 0 ) {
180180 // Array.emptyObjectArray
181181 ref(defn.ArrayModule .companionModule).select(" emptyObjectArray" .toTermName).ensureApplied
182- } else if (size <= Definitions . MaxTupleArity ) {
182+ } else if (size <= MaxTupleArity ) {
183183 // DynamicTuple.productToArray(tup.asInstanceOf[Product])
184184 ref(defn.DynamicTuple_productToArray ).appliedTo(tup.asInstance(defn.ProductType ))
185185 } else {
@@ -196,7 +196,7 @@ class TuplesOptimizations extends MiniPhase with IdentityDenotTransformer {
196196 /** Create a TupleN (1 <= N < 23) from the elements */
197197 private def knownTupleFromElements (tpes : List [Type ], elements : List [Tree ])(implicit ctx : Context ) = {
198198 val size = elements.size
199- assert(0 < size && size <= Definitions . MaxTupleArity )
199+ assert(0 < size && size <= MaxTupleArity )
200200 val tupleModule = defn.TupleType (size).classSymbol.companionModule
201201 ref(tupleModule).select(nme.apply).appliedToTypes(tpes).appliedToArgs(elements)
202202 }
@@ -206,7 +206,7 @@ class TuplesOptimizations extends MiniPhase with IdentityDenotTransformer {
206206 // Unit for empty tuple
207207 Literal (Constant (())) // TODO should this code be here? Or assert(size > specializedSize)
208208 }
209- else if (size <= Definitions . MaxTupleArity ) {
209+ else if (size <= MaxTupleArity ) {
210210 // TupleN(it.next(), ..., it.next())
211211
212212 // 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 {
222222 }
223223 }
224224
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 )
228229 case tp : AppliedType if defn.isTupleClass(tp.tycon.classSymbol) => Some (acc.reverse ::: tp.args)
229230 case tp if tp.classSymbol == defn.UnitClass => Some (acc.reverse)
230231 case _ => None
231232 }
232- rec(tp.stripTypeVar, Nil )
233+ rec(tp.stripTypeVar, Nil , bound )
233234 }
234235}
0 commit comments