From bb598f59af7b0b09d489ec64123d7cd5cc636f78 Mon Sep 17 00:00:00 2001 From: Eugene Flesselle Date: Fri, 2 Feb 2024 21:43:26 +0100 Subject: [PATCH 1/2] Try other Tuple map method --- library/src/scala/Tuple.scala | 2 +- library/src/scala/runtime/Tuples.scala | 6 ++++-- tests/pos/i14351.scala | 2 +- tests/pos/i8300.scala | 9 ++------- tests/run/tuple-map.scala | 27 +++++++++++++++++++++++--- tests/run/tuple-ops.scala | 8 +++----- 6 files changed, 35 insertions(+), 19 deletions(-) diff --git a/library/src/scala/Tuple.scala b/library/src/scala/Tuple.scala index 3738bd05a19b..a2e3fe5f254c 100644 --- a/library/src/scala/Tuple.scala +++ b/library/src/scala/Tuple.scala @@ -56,7 +56,7 @@ sealed trait Tuple extends Product { * If the tuple is of the form `a1 *: ... *: Tuple` (that is, the tail is not known * to be the cons type. */ - inline def map[F[_]](f: [t] => t => F[t]): Map[this.type, F] = + inline def map[F[_ <: Union[this.type]]](f: (t: Union[this.type]) => F[t.type]): Map[this.type, F] = runtime.Tuples.map(this, f).asInstanceOf[Map[this.type, F]] /** Given a tuple `(a1, ..., am)`, returns the tuple `(a1, ..., an)` consisting diff --git a/library/src/scala/runtime/Tuples.scala b/library/src/scala/runtime/Tuples.scala index 41425e8559ba..5736ed17d701 100644 --- a/library/src/scala/runtime/Tuples.scala +++ b/library/src/scala/runtime/Tuples.scala @@ -598,9 +598,11 @@ object Tuples { ) } - def map[F[_]](self: Tuple, f: [t] => t => F[t]): Tuple = self match { + def map[T <: Tuple, F[_ <: Tuple.Union[T]]](self: T, f: (t: Tuple.Union[T]) => F[t.type]): Tuple = self match { case EmptyTuple => self - case _ => fromIArray(self.productIterator.map(f(_).asInstanceOf[Object]).toArray.asInstanceOf[IArray[Object]]) // TODO use toIArray + case _ => + val iterator = self.productIterator.asInstanceOf[Iterator[Tuple.Union[T]]] + fromIArray(iterator.map(f(_)).toArray.asInstanceOf[IArray[Object]]) // TODO use toIArray } def take(self: Tuple, n: Int): Tuple = { diff --git a/tests/pos/i14351.scala b/tests/pos/i14351.scala index 556e6b1ed64e..d0f5f8b1d889 100644 --- a/tests/pos/i14351.scala +++ b/tests/pos/i14351.scala @@ -1 +1 @@ -val p: (Option[Int], Option[String]) = (1,"foo").map([T] => (x: T) => Option.apply[T](x)) +val p: (Option[Int], Option[String]) = (1,"foo").map(Option(_)) diff --git a/tests/pos/i8300.scala b/tests/pos/i8300.scala index f106b24dbd1c..ec8ef6c52025 100644 --- a/tests/pos/i8300.scala +++ b/tests/pos/i8300.scala @@ -6,10 +6,5 @@ type Bar[X] = X match { } object Test: - (Set(1, 2, 3), List("a", "b")).map( - [A] => - (a: A) => - a match { - case it: Iterable[x] => it.map(Tuple1(_)).asInstanceOf[Bar[A]] - } - ) + (Set(1, 2, 3), List("a", "b")).map: + a => a.map(Tuple1(_)).asInstanceOf[Bar[a.type]] diff --git a/tests/run/tuple-map.scala b/tests/run/tuple-map.scala index 02c2803a6a27..1562809bf7a6 100644 --- a/tests/run/tuple-map.scala +++ b/tests/run/tuple-map.scala @@ -4,14 +4,35 @@ object Test extends App { val tuple: Tuple = ("1", "2", "3", "4", "5") val tupleXXL: Tuple = ("11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35") - type Id[X] = X - val f: [t] => t => Id[t] = [t] => (x: t) => { + type F[X] = String + val f: (t: Any) => F[t.type] = x => { val str = x.asInstanceOf[String] - str.updated(0, (str(0) + 1).toChar).asInstanceOf[t] + str.updated(0, (str(0) + 1).toChar) } // Test all possible combinations of making println(emptyTuple.map(f)) println(tuple.map(f)) println(tupleXXL.map(f)) + + // NOTE F is needed in ascription of f above for inference of .map + def alternative: Unit = + val f: (t: Any) => String = x => { + val str = x.asInstanceOf[String] + str.updated(0, (str(0) + 1).toChar) + } + println(emptyTuple.map[F](f)) + println(tuple.map[F](f)) + println(tupleXXL.map[F](f)) + + // Given the body of f, the following is more likely to occur in practice: + def withoutWidening: Unit = + val emptyTuple = Tuple() + val tuple = ("1", "2", "3", "4", "5") + val tupleXXL = ("11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35") + val f: (s: String) => F[s.type] = str => str.updated(0, (str(0) + 1).toChar) + println(emptyTuple.map(f)) + println(tuple.map(f)) + println(tupleXXL.map(f)) + } diff --git a/tests/run/tuple-ops.scala b/tests/run/tuple-ops.scala index 31808da172d0..6ed9cdbe4755 100644 --- a/tests/run/tuple-ops.scala +++ b/tests/run/tuple-ops.scala @@ -13,13 +13,11 @@ val r5: Unit = a.zip(d) // Map case class Foo[X](x: X) -val r6: (Int, Int, Int) = a.map[[t] =>> Int]([t] => (x: t) => x match { - case x: Int => x * x - case _ => ??? -}) +val r6: (Int, Int, Int) = a.map[[t] =>> Int](x => x * x) val r7: ((1, Foo[1]), (2, Foo[2]), (3, Foo[3])) = - a.map[[t] =>> (t, Foo[t])]( [t] => (x: t) => (x, Foo(x)) ) + a.map[[t] =>> (t, Foo[t])](x => (x, Foo(x))) + // NOTE might not need give type param if had `precise` modifier for x // More Zip val t1: Int *: Long *: Tuple = (1, 2l, 100, 200) From 7888a52d5023d5b6dbea66a4ad9c56082591e619 Mon Sep 17 00:00:00 2001 From: Eugene Flesselle Date: Sat, 3 Feb 2024 01:43:15 +0100 Subject: [PATCH 2/2] Update cats and spire community projects --- community-build/community-projects/cats | 2 +- community-build/community-projects/spire | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/community-build/community-projects/cats b/community-build/community-projects/cats index 771c6c802f59..759315411313 160000 --- a/community-build/community-projects/cats +++ b/community-build/community-projects/cats @@ -1 +1 @@ -Subproject commit 771c6c802f59c72dbc1be1898081c9c882ddfeb0 +Subproject commit 7593154113135d641b8f974fd5e7cad7c00b0a35 diff --git a/community-build/community-projects/spire b/community-build/community-projects/spire index bc524eeea735..dbb36322977a 160000 --- a/community-build/community-projects/spire +++ b/community-build/community-projects/spire @@ -1 +1 @@ -Subproject commit bc524eeea735a3cf4d5108039f95950b024a14e4 +Subproject commit dbb36322977ae947541cc231f646fe69bc544345