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)]