From 12e7c9e982c1317bcf251b535fd124c6d017005b Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 4 Dec 2023 10:32:16 +0100 Subject: [PATCH] Introduce `Tuple.ReverseOnto` and use it in `Tuple.reverse` --- library/src/scala/Tuple.scala | 13 +++++-------- tests/pos/TupleReverse.scala | 16 ++++++++++++++++ tests/pos/TupleReverseOnto.scala | 15 +++++++++++++++ .../stdlibExperimentalDefinitions.scala | 10 ++++------ 4 files changed, 40 insertions(+), 14 deletions(-) create mode 100644 tests/pos/TupleReverse.scala create mode 100644 tests/pos/TupleReverseOnto.scala diff --git a/library/src/scala/Tuple.scala b/library/src/scala/Tuple.scala index 6993b8202082..4f756f76db73 100644 --- a/library/src/scala/Tuple.scala +++ b/library/src/scala/Tuple.scala @@ -202,16 +202,13 @@ object Tuple { /** Type of the reversed tuple */ @experimental - type Reverse[X <: Tuple] = Helpers.ReverseImpl[EmptyTuple, X] + type Reverse[X <: Tuple] = ReverseOnto[X, EmptyTuple] + /** Prepends all elements of a tuple in reverse order onto the other tuple */ @experimental - object Helpers: - - /** Type of the reversed tuple */ - @experimental - type ReverseImpl[Acc <: Tuple, X <: Tuple] <: Tuple = X match - case x *: xs => ReverseImpl[x *: Acc, xs] - case EmptyTuple => Acc + type ReverseOnto[From <: Tuple, +To <: Tuple] <: Tuple = From match + case x *: xs => ReverseOnto[xs, x *: To] + case EmptyTuple => To /** Transforms a tuple `(T1, ..., Tn)` into `(T1, ..., Ti)`. */ type Take[T <: Tuple, N <: Int] <: Tuple = N match { diff --git a/tests/pos/TupleReverse.scala b/tests/pos/TupleReverse.scala new file mode 100644 index 000000000000..9b83280afcf1 --- /dev/null +++ b/tests/pos/TupleReverse.scala @@ -0,0 +1,16 @@ +import scala.Tuple.* +def test[T1, T2, T3, T4] = + summon[Reverse[EmptyTuple] =:= EmptyTuple] + summon[Reverse[T1 *: EmptyTuple] =:= T1 *: EmptyTuple] + summon[Reverse[(T1, T2)] =:= (T2, T1)] + summon[Reverse[(T1, T2, T3)] =:= (T3, T2, T1)] + summon[Reverse[(T1, T2, T3, T4)] =:= (T4, T3, T2, T1)] + + summon[Reverse[(T1, T2, T3, T4)] =:= Reverse[(T1, T2, T3, T4)]] + summon[Reverse[(T1, T2, T3, T4)] <:< Reverse[(Any, Any, Any, Any)]] + +def test2[Tup <: Tuple] = + summon[Reverse[Tup] =:= Reverse[Tup]] + +def test3[T1, T2, T3, T4](tup1: (T1, T2, T3, T4)) = + summon[Reverse[tup1.type] =:= (T4, T3, T2, T1)] diff --git a/tests/pos/TupleReverseOnto.scala b/tests/pos/TupleReverseOnto.scala new file mode 100644 index 000000000000..bef2d0949b29 --- /dev/null +++ b/tests/pos/TupleReverseOnto.scala @@ -0,0 +1,15 @@ +import scala.Tuple.* +def test[T1, T2, T3, T4] = + summon[ReverseOnto[(T1, T2), (T3, T4)] =:= ReverseOnto[(T1, T2), (T3, T4)]] + summon[ReverseOnto[(T1, T2), (T3, T4)] =:= (T2, T1, T3, T4)] + summon[ReverseOnto[(T1, T2), (T3, T4)] <:< (Any, Any, Any, Any)] + summon[ReverseOnto[(T1, T2), (T3, T4)] <:< ReverseOnto[(Any, Any), (Any, Any)]] + summon[ReverseOnto[(T1, T2), (T3, T4)] =:= Concat[Reverse[(T1, T2)], (T3, T4)]] + +def test2[Tup1 <: Tuple, Tup2 <: Tuple] = + summon[ReverseOnto[EmptyTuple, Tup1] =:= Tup1] + summon[ReverseOnto[Tup1, EmptyTuple] =:= Reverse[Tup1]] + +def test3[T1, T2, T3, T4](tup1: (T1, T2), tup2: (T3, T4)) = + summon[ReverseOnto[tup1.type, tup2.type] <:< (T2, T1, T3, T4)] + summon[ReverseOnto[tup1.type, tup2.type] =:= T2 *: T1 *: tup2.type] diff --git a/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala b/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala index a01c71724b0e..afa10ad6af6f 100644 --- a/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala +++ b/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala @@ -92,12 +92,10 @@ val experimentalDefinitionInLibrary = Set( "scala.quoted.Quotes.reflectModule.TermParamClauseMethods.hasErasedArgs", // New feature: reverse method on Tuple - "scala.Tuple.reverse", - "scala.Tuple$.Helpers", - "scala.Tuple$.Helpers$", - "scala.Tuple$.Helpers$.ReverseImpl", - "scala.Tuple$.Reverse", - "scala.runtime.Tuples$.reverse" + "scala.Tuple.reverse", // can be stabilized in 3.4 + "scala.Tuple$.Reverse", // can be stabilized in 3.4 + "scala.Tuple$.ReverseOnto", // can be stabilized in 3.4 + "scala.runtime.Tuples$.reverse", // can be stabilized in 3.4 )