From 034207bf9068bfe3d78be3208348a4b86e885217 Mon Sep 17 00:00:00 2001 From: Eugene Flesselle Date: Mon, 29 Apr 2024 12:07:54 +0200 Subject: [PATCH] Refine the bounds of the `Tuple.Filter` type lambda predicate .. to only require it be defined on the elements of the tuple. This is one of the ongoing proposed tuple improvements, addressing #19175. As carefully pointed out by @sjrd, this _is_ a potential breaking change. See tests/neg/tuple-filter-compat.scala for an example. This is not an unprecedented change however, the analogous improvements were made to `Tuple.{Map, FlatMap}` in 28a695ef. --- library/src/scala/Tuple.scala | 2 +- tests/neg/tuple-filter-compat.scala | 12 ++++++++++++ tests/pos/tuple-filter.scala | 6 ++++++ 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 tests/neg/tuple-filter-compat.scala diff --git a/library/src/scala/Tuple.scala b/library/src/scala/Tuple.scala index 8074fe3664e5..060f2b5492b8 100644 --- a/library/src/scala/Tuple.scala +++ b/library/src/scala/Tuple.scala @@ -166,7 +166,7 @@ object Tuple { * ``` * @syntax markdown */ - type Filter[Tup <: Tuple, P[_] <: Boolean] <: Tuple = Tup match { + type Filter[Tup <: Tuple, P[_ <: Union[Tup]] <: Boolean] <: Tuple = Tup match { case EmptyTuple => EmptyTuple case h *: t => P[h] match { case true => h *: Filter[t, P] diff --git a/tests/neg/tuple-filter-compat.scala b/tests/neg/tuple-filter-compat.scala new file mode 100644 index 000000000000..f50837fc1d4b --- /dev/null +++ b/tests/neg/tuple-filter-compat.scala @@ -0,0 +1,12 @@ + +type OldFilter[Tup <: Tuple, P[_] <: Boolean] = Nothing +type NewFilter[Tup <: Tuple, P[_ <: Tuple.Union[Tup]] <: Boolean] = Nothing + +trait A: + type X >: OldFilter <: OldFilter + +trait B1 extends A: + type X = OldFilter // ok + +trait B2 extends A: + type X = NewFilter // error: breaking change diff --git a/tests/pos/tuple-filter.scala b/tests/pos/tuple-filter.scala index 2c9638b2e47b..f67518f171f0 100644 --- a/tests/pos/tuple-filter.scala +++ b/tests/pos/tuple-filter.scala @@ -1,10 +1,16 @@ +import scala.compiletime.ops.int.< + type P[x] <: Boolean = x match { case 3 => false case _ => true } + type RejectAll[x] = false +type Pos[X <: Int] = 0 < X + def Test = summon[Tuple.Filter[(1, 2, 3, 4), P] =:= (1, 2, 4)] summon[Tuple.Filter[(1, 2, 3, 4), RejectAll] =:= EmptyTuple] summon[Tuple.Filter[EmptyTuple, P] =:= EmptyTuple] + summon[Tuple.Filter[(1, -2, 3, -4), Pos] =:= (1, 3)]