From 4983ebb94f8abc9cdfa4b46ff31910c3f03b71b3 Mon Sep 17 00:00:00 2001 From: Decel <8268812+Decel@users.noreply.github.com> Date: Thu, 30 Mar 2023 21:58:00 +0200 Subject: [PATCH] Allow Tuple.Head and Tuple.Tail to accept any Tuple --- compiler/test/dotc/pos-test-pickling.blacklist | 2 ++ library/src/scala/Tuple.scala | 9 +++++++-- tests/{neg => pos}/i11982a.scala | 0 tests/pos/i17186.scala | 5 +++++ 4 files changed, 14 insertions(+), 2 deletions(-) rename tests/{neg => pos}/i11982a.scala (100%) create mode 100644 tests/pos/i17186.scala diff --git a/compiler/test/dotc/pos-test-pickling.blacklist b/compiler/test/dotc/pos-test-pickling.blacklist index d1dd83f36ff7..97663bbcc09b 100644 --- a/compiler/test/dotc/pos-test-pickling.blacklist +++ b/compiler/test/dotc/pos-test-pickling.blacklist @@ -21,6 +21,8 @@ i15181.scala i15922.scala t5031_2.scala i16997.scala +i17186.scala +i11982a.scala # Tree is huge and blows stack for printing Text i7034.scala diff --git a/library/src/scala/Tuple.scala b/library/src/scala/Tuple.scala index fa72e320b560..1157cec919fa 100644 --- a/library/src/scala/Tuple.scala +++ b/library/src/scala/Tuple.scala @@ -89,7 +89,11 @@ object Tuple { } /** Type of the head of a tuple */ - type Head[X <: NonEmptyTuple] = X match { + // Only bounded by `<: Tuple` not `<: NonEmptyTuple` + // even though it only matches non-empty tuples. + // This allows an irreducible type like `Tuple.Head[Tuple.Tail[X]]` + // to avoid running into type bounds violation checks. + type Head[X <: Tuple] = X match { case x *: _ => x } @@ -101,7 +105,8 @@ object Tuple { } /** Type of the tail of a tuple */ - type Tail[X <: NonEmptyTuple] <: Tuple = X match { + // See Head for why not `<: NonEmptyTuple` + type Tail[X <: Tuple] <: Tuple = X match { case _ *: xs => xs } diff --git a/tests/neg/i11982a.scala b/tests/pos/i11982a.scala similarity index 100% rename from tests/neg/i11982a.scala rename to tests/pos/i11982a.scala diff --git a/tests/pos/i17186.scala b/tests/pos/i17186.scala new file mode 100644 index 000000000000..36efd647816c --- /dev/null +++ b/tests/pos/i17186.scala @@ -0,0 +1,5 @@ +type SecondOfTwo[X <: Tuple2[Any, Any]] = Tuple.Head[Tuple.Tail[X]] +val a = implicitly[SecondOfTwo[Tuple2[Int, String]] =:= String] + +type LastOfThree[X <: Tuple3[Any, Any, Any]] = Tuple.Tail[Tuple.Tail[X]] +val b = implicitly[LastOfThree[Tuple3[Int, String, Boolean]] =:= Tuple1[Boolean]]