From a964745b006a72988fe7561bbcc110bbbdc3e9cc Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 9 Jun 2021 15:26:21 +0200 Subject: [PATCH 1/2] Fix Tuple.toList return type This method failed for any subtype of `Tuple`. It only worked for `Tuple` and `TupleN` as these define their own `toList`. Fixes #12721 --- compiler/test/dotc/pos-test-pickling.blacklist | 1 + compiler/test/dotc/run-test-pickling.blacklist | 1 + library/src/scala/Tuple.scala | 5 ++--- tests/pos/i12721.scala | 7 +++++++ 4 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 tests/pos/i12721.scala diff --git a/compiler/test/dotc/pos-test-pickling.blacklist b/compiler/test/dotc/pos-test-pickling.blacklist index e20b5848b40e..5b3ae23f575b 100644 --- a/compiler/test/dotc/pos-test-pickling.blacklist +++ b/compiler/test/dotc/pos-test-pickling.blacklist @@ -44,6 +44,7 @@ i5720.scala # Tuples toexproftuple.scala i7580.scala +i12721.scala # Nullability nullable.scala diff --git a/compiler/test/dotc/run-test-pickling.blacklist b/compiler/test/dotc/run-test-pickling.blacklist index 873c34a19c42..5aa0fa2c26ec 100644 --- a/compiler/test/dotc/run-test-pickling.blacklist +++ b/compiler/test/dotc/run-test-pickling.blacklist @@ -22,6 +22,7 @@ tuple-zip.scala tuples1.scala tuples1a.scala tuples1b.scala +toList.scala typeCheckErrors.scala typeclass-derivation-doc-example.scala typeclass-derivation1.scala diff --git a/library/src/scala/Tuple.scala b/library/src/scala/Tuple.scala index c6db4d0b83bc..ed91a5b9e857 100644 --- a/library/src/scala/Tuple.scala +++ b/library/src/scala/Tuple.scala @@ -12,9 +12,8 @@ sealed trait Tuple extends Product { runtime.Tuples.toArray(this) /** Create a copy this tuple as a List */ - inline def toList: List[Union[this.type]] = - this.productIterator.toList - .asInstanceOf[List[Union[this.type]]] + inline def toList[This >: this.type <: Tuple]: List[Union[This]] = + this.productIterator.toList.asInstanceOf[List[Union[This]]] /** Create a copy this tuple as an IArray */ inline def toIArray: IArray[Object] = diff --git a/tests/pos/i12721.scala b/tests/pos/i12721.scala new file mode 100644 index 000000000000..f0c66240f7d4 --- /dev/null +++ b/tests/pos/i12721.scala @@ -0,0 +1,7 @@ +def bar(t: Any): Int = 1 +def foo(t: AnyRef): Unit = + (??? : Tuple).toList.map(bar) + (??? : EmptyTuple).toList.map(bar) + (??? : NonEmptyTuple).toList.map(bar) + (??? : *:[?, ?]).toList.map(bar) + (??? : (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int)).toList.map(bar) \ No newline at end of file From a2391b9a242e965ef84612690720a887cec52ab8 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 28 Jul 2021 09:50:02 +0200 Subject: [PATCH 2/2] Hide old Tuple.toList and implement as extension This should in theory be backwards TASTy compatible. Fixes #12721 --- library/src/scala/Tuple.scala | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/library/src/scala/Tuple.scala b/library/src/scala/Tuple.scala index ed91a5b9e857..66b5547e99a0 100644 --- a/library/src/scala/Tuple.scala +++ b/library/src/scala/Tuple.scala @@ -11,9 +11,15 @@ sealed trait Tuple extends Product { inline def toArray: Array[Object] = runtime.Tuples.toArray(this) + // NOTE: Replaced by `toList` extension method in the `Tuple` object. + // Kept this version of the method as `private[scala]` to be + // able to unpickle older TASTy files. + // TODO: When we can break TASTy compat, replace this method with one that has the following signature + // `inline def toList[This >: this.type <: Tuple]: List[Union[This]]` + // and remove the extension method in the `Tuple` object. /** Create a copy this tuple as a List */ - inline def toList[This >: this.type <: Tuple]: List[Union[This]] = - this.productIterator.toList.asInstanceOf[List[Union[This]]] + private[scala] inline def toList: List[Union[this.type]] = + this.productIterator.toList.asInstanceOf[List[Union[this.type]]] /** Create a copy this tuple as an IArray */ inline def toIArray: IArray[Object] = @@ -231,6 +237,13 @@ object Tuple { def fromProductTyped[P <: Product](p: P)(using m: scala.deriving.Mirror.ProductOf[P]): m.MirroredElemTypes = runtime.Tuples.fromProduct(p).asInstanceOf[m.MirroredElemTypes] + + // TODO: When we can break TASTy compat, move this method to `Tuple` class and use the following signature + // `inline def toList[This >: this.type <: Tuple]: List[Union[This]]` + /** Create a copy this tuple as a List */ + extension [This <: Tuple](inline tuple: This) + inline def toList: List[Union[This]] = + tuple.productIterator.toList.asInstanceOf[List[Union[This]]] } /** A tuple of 0 elements */