From 995d63b140f1078a7c853d92d8fce2138c474c1e Mon Sep 17 00:00:00 2001 From: Eugene Flesselle Date: Tue, 30 Jul 2024 14:27:50 +0200 Subject: [PATCH 1/2] Combine cases of `Tuple.Zip` disjoint from `(h1 *: t1, h2 *: t2)` If we reach the second case of `Zip[T1 <: Tuple, T2 <: Tuple]`, then we know `(T1, T2)` is disjoint from `(NonEmptyTuple, NonEmptyTuple)`, from which we can conclude at least one of the two is an `EmptyTuple`. Addressing #19175 --- library/src/scala/Tuple.scala | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/library/src/scala/Tuple.scala b/library/src/scala/Tuple.scala index 8074fe3664e5..8291e17a5cfc 100644 --- a/library/src/scala/Tuple.scala +++ b/library/src/scala/Tuple.scala @@ -175,15 +175,12 @@ object Tuple { } /** Given two tuples, `A1 *: ... *: An * At` and `B1 *: ... *: Bn *: Bt` - * where at least one of `At` or `Bt` is `EmptyTuple` or `Tuple`, - * returns the tuple type `(A1, B1) *: ... *: (An, Bn) *: Ct` - * where `Ct` is `EmptyTuple` if `At` or `Bt` is `EmptyTuple`, otherwise `Ct` is `Tuple`. + * where at least one of `At` or `Bt` is `EmptyTuple`, + * returns the tuple type `(A1, B1) *: ... *: (An, Bn) *: EmptyTuple`. */ type Zip[T1 <: Tuple, T2 <: Tuple] <: Tuple = (T1, T2) match { case (h1 *: t1, h2 *: t2) => (h1, h2) *: Zip[t1, t2] - case (EmptyTuple, _) => EmptyTuple - case (_, EmptyTuple) => EmptyTuple - case _ => Tuple + case _ => EmptyTuple } /** Converts a tuple `(F[T1], ..., F[Tn])` to `(T1, ... Tn)` */ From 14bf406e02488e7c333a94989cbc1f7fff07b625 Mon Sep 17 00:00:00 2001 From: Eugene Flesselle Date: Tue, 12 Nov 2024 10:12:29 +0100 Subject: [PATCH 2/2] Test reduction of Tuple.Zip --- tests/pos/tuple-zip.scala | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tests/pos/tuple-zip.scala diff --git a/tests/pos/tuple-zip.scala b/tests/pos/tuple-zip.scala new file mode 100644 index 000000000000..980dff9433a6 --- /dev/null +++ b/tests/pos/tuple-zip.scala @@ -0,0 +1,20 @@ + +import scala.Tuple.Zip + +type A +type B +type C + +def Test = + + summon[Zip[A *: B *: C *: EmptyTuple, C *: B *: A *: EmptyTuple] =:= (A, C) *: (B, B) *: (C, A) *: EmptyTuple] + + summon[Zip[A *: B *: EmptyTuple, C *: B *: A *: EmptyTuple] =:= (A, C) *: (B, B) *: EmptyTuple] + summon[Zip[A *: B *: C *: EmptyTuple, C *: B *: EmptyTuple] =:= (A, C) *: (B, B) *: EmptyTuple] + + summon[Zip[A *: B *: C *: Tuple, C *: B *: A *: Tuple] =:= (A, C) *: (B, B) *: (C, A) *: Zip[Tuple, Tuple]] + summon[Zip[A *: B *: C *: Tuple, C *: B *: A *: Tuple] <:< (A, C) *: (B, B) *: (C, A) *: Tuple] + + summon[Zip[A *: B *: Tuple, C *: B *: A *: Tuple] =:= (A, C) *: (B, B) *: Zip[Tuple, A *: Tuple]] + summon[Zip[A *: B *: NonEmptyTuple, C *: B *: A *: Tuple] =:= (A, C) *: (B, B) *: Zip[NonEmptyTuple, A *: Tuple]] + summon[Zip[A *: B *: EmptyTuple, C *: B *: A *: Tuple] =:= (A, C) *: (B, B) *: EmptyTuple]