diff --git a/library/src-3.x/scala/Tuple.scala b/library/src-3.x/scala/Tuple.scala index 994482d4e4c3..8973dc61fec1 100644 --- a/library/src-3.x/scala/Tuple.scala +++ b/library/src-3.x/scala/Tuple.scala @@ -200,6 +200,9 @@ object Tuple { runtime.DynamicTuple.dynamicFromArray[Tuple](xs2) } + def fromProduct(product: Product): Tuple = + runtime.DynamicTuple.dynamicFromProduct[Tuple](product) + } sealed trait NonEmptyTuple extends Tuple { diff --git a/library/src-3.x/scala/runtime/DynamicTuple.scala b/library/src-3.x/scala/runtime/DynamicTuple.scala index a3fe8055227a..ab26ca839fcc 100644 --- a/library/src-3.x/scala/runtime/DynamicTuple.scala +++ b/library/src-3.x/scala/runtime/DynamicTuple.scala @@ -57,6 +57,125 @@ object DynamicTuple { case _ => TupleXXL(xs).asInstanceOf[T] } + def dynamicFromProduct[T <: Tuple](xs: Product): T = (xs.productArity match { + case 1 => + xs match { + case xs: Tuple1[_] => xs + case xs => Tuple1(xs.productElement(0)) + } + case 2 => + xs match { + case xs: Tuple2[_, _] => xs + case xs => Tuple2(xs.productElement(0), xs.productElement(1)) + } + case 3 => + xs match { + case xs: Tuple3[_, _, _] => xs + case xs => Tuple3(xs.productElement(0), xs.productElement(1), xs.productElement(2)) + } + case 4 => + xs match { + case xs: Tuple4[_, _, _, _] => xs + case xs => Tuple4(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3)) + } + case 5 => + xs match { + case xs: Tuple5[_, _, _, _, _] => xs + case xs => Tuple5(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4)) + } + case 6 => + xs match { + case xs: Tuple6[_, _, _, _, _, _] => xs + case xs => Tuple6(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5)) + } + case 7 => + xs match { + case xs: Tuple7[_, _, _, _, _, _, _] => xs + case xs => Tuple7(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6)) + } + case 8 => + xs match { + case xs: Tuple8[_, _, _, _, _, _, _, _] => xs + case xs => Tuple8(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7)) + } + case 9 => + xs match { + case xs: Tuple9[_, _, _, _, _, _, _, _, _] => xs + case xs => Tuple9(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8)) + } + case 10 => + xs match { + case xs: Tuple10[_, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple10(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9)) + } + case 11 => + xs match { + case xs: Tuple11[_, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple11(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10)) + } + case 12 => + xs match { + case xs: Tuple12[_, _, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple12(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10), xs.productElement(11)) + } + case 13 => + xs match { + case xs: Tuple13[_, _, _, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple13(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10), xs.productElement(11), xs.productElement(12)) + } + case 14 => + xs match { + case xs: Tuple14[_, _, _, _, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple14(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10), xs.productElement(11), xs.productElement(12), xs.productElement(13)) + } + case 15 => + xs match { + case xs: Tuple15[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple15(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10), xs.productElement(11), xs.productElement(12), xs.productElement(13), xs.productElement(14)) + } + case 16 => + xs match { + case xs: Tuple16[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple16(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10), xs.productElement(11), xs.productElement(12), xs.productElement(13), xs.productElement(14), xs.productElement(15)) + } + case 17 => + xs match { + case xs: Tuple17[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple17(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10), xs.productElement(11), xs.productElement(12), xs.productElement(13), xs.productElement(14), xs.productElement(15), xs.productElement(16)) + } + case 18 => + xs match { + case xs: Tuple18[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple18(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10), xs.productElement(11), xs.productElement(12), xs.productElement(13), xs.productElement(14), xs.productElement(15), xs.productElement(16), xs.productElement(17)) + } + case 19 => + xs match { + case xs: Tuple19[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple19(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10), xs.productElement(11), xs.productElement(12), xs.productElement(13), xs.productElement(14), xs.productElement(15), xs.productElement(16), xs.productElement(17), xs.productElement(18)) + } + case 20 => + xs match { + case xs: Tuple20[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple20(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10), xs.productElement(11), xs.productElement(12), xs.productElement(13), xs.productElement(14), xs.productElement(15), xs.productElement(16), xs.productElement(17), xs.productElement(18), xs.productElement(19)) + } + case 21 => + xs match { + case xs: Tuple21[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple21(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10), xs.productElement(11), xs.productElement(12), xs.productElement(13), xs.productElement(14), xs.productElement(15), xs.productElement(16), xs.productElement(17), xs.productElement(18), xs.productElement(19), xs.productElement(20)) + } + case 22 => + xs match { + case xs: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple22(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10), xs.productElement(11), xs.productElement(12), xs.productElement(13), xs.productElement(14), xs.productElement(15), xs.productElement(16), xs.productElement(17), xs.productElement(18), xs.productElement(19), xs.productElement(20), xs.productElement(21)) + } + case _ => + xs match { + case xs: TupleXXL => xs + case xs => TupleXXL(xs.productIterator.map(_.asInstanceOf[Object]).toArray) + } + }).asInstanceOf[T] + + def dynamicToArray(self: Tuple): Array[Object] = (self: Any) match { case self: Unit => scala.runtime.DynamicTuple.empty$Array diff --git a/tests/run/Tuple-fromProduct.check b/tests/run/Tuple-fromProduct.check new file mode 100644 index 000000000000..a8bbc5fbba68 --- /dev/null +++ b/tests/run/Tuple-fromProduct.check @@ -0,0 +1,47 @@ +(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) +(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/Tuple-fromProduct.scala b/tests/run/Tuple-fromProduct.scala new file mode 100644 index 000000000000..8d2ca111e38d --- /dev/null +++ b/tests/run/Tuple-fromProduct.scala @@ -0,0 +1,46 @@ + +object Test { + def main(args: Array[String]): Unit = { + + def testProduct(product: Product): Unit = { + val t: Tuple = Tuple.fromProduct(product) + println(t) + } + + testProduct(Tuple1(1)) + testProduct((1, 2)) + testProduct((1, 2, 3)) + testProduct((1, 2, 3, 4)) + testProduct((1, 2, 3, 4, 5)) + testProduct((1, 2, 3, 4, 5, 6)) + testProduct((1, 2, 3, 4, 5, 6, 7)) + testProduct((1, 2, 3, 4, 5, 6, 7, 8)) + testProduct((1, 2, 3, 4, 5, 6, 7, 8, 9)) + testProduct((1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) + testProduct((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)) + testProduct((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)) + testProduct((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)) + testProduct((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)) + testProduct((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)) + testProduct((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)) + testProduct((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17)) + testProduct((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18)) + testProduct((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)) + testProduct((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)) + testProduct((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21)) + testProduct((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22)) + // FIXME ProductN for N > 22 does not extends product +// testProduct((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23)) +// testProduct((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24)) +// testProduct((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)) + + class MyProduct(val productArity: Int) extends Product { + def productElement(n: Int): Any = n + 1 + def canEqual(that: Any): Boolean = false + } + + for (i <- 1 to 25) + testProduct(new MyProduct(i)) + + } +}