diff --git a/library/src/scala/Tuple.scala b/library/src/scala/Tuple.scala index 784170c524ae..06d258e3e503 100644 --- a/library/src/scala/Tuple.scala +++ b/library/src/scala/Tuple.scala @@ -21,6 +21,11 @@ sealed trait Tuple extends Product { inline def toIArray: IArray[Object] = runtime.Tuples.toIArray(this) + /** Return a copy of `this` tuple with an element appended */ + @experimental + inline def :* [This >: this.type <: Tuple, L] (x: L): Append[This, L] = + runtime.Tuples.append(x, this).asInstanceOf[Append[This, L]] + /** Return a new tuple by prepending the element to `this` tuple. * This operation is O(this.size) */ @@ -78,6 +83,13 @@ sealed trait Tuple extends Product { object Tuple { + /** Type of a tuple with an element appended */ + @experimental + type Append[X <: Tuple, Y] <: Tuple = X match { + case EmptyTuple => Y *: EmptyTuple + case x *: xs => x *: Append[xs, Y] + } + /** Type of the head of a tuple */ type Head[X <: NonEmptyTuple] = X match { case x *: _ => x diff --git a/library/src/scala/runtime/Tuples.scala b/library/src/scala/runtime/Tuples.scala index 1c81782acecb..bfb863bcc0f0 100644 --- a/library/src/scala/runtime/Tuples.scala +++ b/library/src/scala/runtime/Tuples.scala @@ -357,6 +357,82 @@ object Tuples { case _ => specialCaseTail(self) } + // Append for TupleXXL + private def xxlAppend(x: Any, xxl: TupleXXL): TupleXXL = { + val arr = new Array[Object](xxl.productArity + 1) + arr(xxl.productArity) = x.asInstanceOf[Object] + System.arraycopy(xxl.elems, 0, arr, 0, xxl.productArity) + TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]) + } + + // Append for Tuple1 to Tuple22 + private def specialCaseAppend(x: Any, self: Tuple): Tuple = { + (self: Any) match { + case EmptyTuple => + Tuple1(x) + case self: Tuple1[_] => + Tuple2(self._1, x) + case self: Tuple2[_, _] => + Tuple3(self._1, self._2, x) + case self: Tuple3[_, _, _] => + Tuple4(self._1, self._2, self._3, x) + case self: Tuple4[_, _, _, _] => + Tuple5(self._1, self._2, self._3, self._4, x) + case self: Tuple5[_, _, _, _, _] => + Tuple6(self._1, self._2, self._3, self._4, self._5, x) + case self: Tuple6[_, _, _, _, _, _] => + Tuple7(self._1, self._2, self._3, self._4, self._5, self._6, x) + case self: Tuple7[_, _, _, _, _, _, _] => + Tuple8(self._1, self._2, self._3, self._4, self._5, self._6, self._7, x) + case self: Tuple8[_, _, _, _, _, _, _, _] => + Tuple9(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, x) + case self: Tuple9[_, _, _, _, _, _, _, _, _] => + Tuple10(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, x) + case self: Tuple10[_, _, _, _, _, _, _, _, _, _] => + Tuple11(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, x) + case self: Tuple11[_, _, _, _, _, _, _, _, _, _, _] => + Tuple12(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, x) + case self: Tuple12[_, _, _, _, _, _, _, _, _, _, _, _] => + Tuple13(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, x) + case self: Tuple13[_, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple14(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, x) + case self: Tuple14[_, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple15(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, x) + case self: Tuple15[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple16(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, x) + case self: Tuple16[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple17(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, x) + case self: Tuple17[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple18(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, x) + case self: Tuple18[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple19(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, x) + case self: Tuple19[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple20(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, x) + case self: Tuple20[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple21(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, x) + case self: Tuple21[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple22(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21, x) + case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + val arr: Array[Object] = Array( + self._1.asInstanceOf[Object], self._2.asInstanceOf[Object], + self._3.asInstanceOf[Object], self._4.asInstanceOf[Object], self._5.asInstanceOf[Object], + self._6.asInstanceOf[Object], self._7.asInstanceOf[Object], self._8.asInstanceOf[Object], + self._9.asInstanceOf[Object], self._10.asInstanceOf[Object], self._11.asInstanceOf[Object], + self._12.asInstanceOf[Object], self._13.asInstanceOf[Object], self._14.asInstanceOf[Object], + self._15.asInstanceOf[Object], self._16.asInstanceOf[Object], self._17.asInstanceOf[Object], + self._18.asInstanceOf[Object], self._19.asInstanceOf[Object], self._20.asInstanceOf[Object], + self._21.asInstanceOf[Object], self._22.asInstanceOf[Object], x.asInstanceOf[Object] + ) + TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[Tuple] + } + } + + @experimental + def append(x: Any, self: Tuple): Tuple = (self: Any) match { + case xxl: TupleXXL => xxlAppend(x, xxl).asInstanceOf[Tuple] + case _ => specialCaseAppend(x, self) + } + // Init for TupleXXL private def xxlInit(xxl: TupleXXL): Tuple = { if (xxl.productArity == 23) { diff --git a/project/MiMaFilters.scala b/project/MiMaFilters.scala index 9fe7da22fb2a..e37bce1b3cf9 100644 --- a/project/MiMaFilters.scala +++ b/project/MiMaFilters.scala @@ -6,6 +6,7 @@ object MiMaFilters { val Library: Seq[ProblemFilter] = Seq( // Experimental APIs that can be added in 3.2.0 ProblemFilters.exclude[DirectMissingMethodProblem]("scala.runtime.Tuples.init"), - ProblemFilters.exclude[DirectMissingMethodProblem]("scala.runtime.Tuples.last") + ProblemFilters.exclude[DirectMissingMethodProblem]("scala.runtime.Tuples.last"), + ProblemFilters.exclude[DirectMissingMethodProblem]("scala.runtime.Tuples.append") ) } diff --git a/tests/run-deep-subtype/Tuple-append.check b/tests/run-deep-subtype/Tuple-append.check new file mode 100644 index 000000000000..96c717f2aef0 --- /dev/null +++ b/tests/run-deep-subtype/Tuple-append.check @@ -0,0 +1,76 @@ +(0) +(0,1) +(0,1,2) +(0,1,2,3) +(0,1,2,3,4) +(0,1,2,3,4,5) +(0,1,2,3,4,5,6) +(0,1,2,3,4,5,6,7) +(0,1,2,3,4,5,6,7,8) +(0,1,2,3,4,5,6,7,8,9) +(0,1,2,3,4,5,6,7,8,9,10) +(0,1,2,3,4,5,6,7,8,9,10,11) +(0,1,2,3,4,5,6,7,8,9,10,11,12) +(0,1,2,3,4,5,6,7,8,9,10,11,12,13) +(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14) +(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15) +(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) +(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17) +(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18) +(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19) +(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20) +(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21) +(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22) +(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23) +(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24) +(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25) +(1) +(1,2) +(1,2,3) +(1,2,3,4) +(1,2,3,4,5) +(1,2,3,4,5,6) +(1,2,3,4,5,6,7) +(1,2,3,4,5,6,7,8) +(1,2,3,4,5,6,7,8,9) +(1,2,3,4,5,6,7,8,9,10) +(1,2,3,4,5,6,7,8,9,10,11) +(1,2,3,4,5,6,7,8,9,10,11,12) +(1,2,3,4,5,6,7,8,9,10,11,12,13) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25) +(1) +(1,2) +(1,2,3) +(1,2,3,4) +(1,2,3,4,5) +(1,2,3,4,5,6) +(1,2,3,4,5,6,7) +(1,2,3,4,5,6,7,8) +(1,2,3,4,5,6,7,8,9) +(1,2,3,4,5,6,7,8,9,10) +(1,2,3,4,5,6,7,8,9,10,11) +(1,2,3,4,5,6,7,8,9,10,11,12) +(1,2,3,4,5,6,7,8,9,10,11,12,13) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24) +(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25) diff --git a/tests/run-deep-subtype/Tuple-append.scala b/tests/run-deep-subtype/Tuple-append.scala new file mode 100644 index 000000000000..d913b4c98e1d --- /dev/null +++ b/tests/run-deep-subtype/Tuple-append.scala @@ -0,0 +1,65 @@ +import scala.reflect.ClassTag + +object Test { + def main(args: Array[String]): Unit = { + def testArray[T: ClassTag](n: Int, elem: Int => T): Unit = { + val t: Tuple = Tuple.fromArray(Array.tabulate(n)(elem)) + println(t :* n) + } + + for (i <- 0 to 25) + testArray(i, j => j) + + println(Tuple() :* 1) + println(Tuple1(1) :* 2) + println((1, 2) :* 3) + println((1, 2, 3) :* 4) + println((1, 2, 3, 4) :* 5) + println((1, 2, 3, 4, 5) :* 6) + println((1, 2, 3, 4, 5, 6) :* 7) + println((1, 2, 3, 4, 5, 6, 7) :* 8) + println((1, 2, 3, 4, 5, 6, 7, 8) :* 9) + println((1, 2, 3, 4, 5, 6, 7, 8, 9) :* 10) + println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10) :* 11) + println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) :* 12) + println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) :* 13) + println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13) :* 14) + println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14) :* 15) + println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) :* 16) + println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16) :* 17) + println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17) :* 18) + println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18) :* 19) + println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19) :* 20) + println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20) :* 21) + println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21) :* 22) + println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22) :* 23) + println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23) :* 24) + println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24) :* 25) + + println(EmptyTuple :* 1) + println((1 *: Tuple()) :* 2) + println((1 *: 2 *: Tuple()) :* 3) + println((1 *: 2 *: 3 *: Tuple()) :* 4) + println((1 *: 2 *: 3 *: 4 *: Tuple()) :* 5) + println((1 *: 2 *: 3 *: 4 *: 5 *: Tuple()) :* 6) + println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: Tuple()) :* 7) + println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: Tuple()) :* 8) + println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: Tuple()) :* 9) + println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: Tuple()) :* 10) + println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: Tuple()) :* 11) + println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: Tuple()) :* 12) + println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: Tuple()) :* 13) + println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: Tuple()) :* 14) + println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: Tuple()) :* 15) + println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: Tuple()) :* 16) + println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: Tuple()) :* 17) + println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: Tuple()) :* 18) + println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: Tuple()) :* 19) + println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: 19 *: Tuple()) :* 20) + println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: 19 *: 20 *: Tuple()) :* 21) + println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: 19 *: 20 *: 21 *: Tuple()) :* 22) + println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: 19 *: 20 *: 21 *: 22 *: Tuple()) :* 23) + println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: 19 *: 20 *: 21 *: 22 *: 23 *: Tuple()) :* 24) + println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: 19 *: 20 *: 21 *: 22 *: 23 *: 24 *: Tuple()) :* 25) + } +}