Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redefine Tuple operations #19185

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/test/dotc/pos-test-pickling.blacklist
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ i17149.scala
tuple-fold.scala
mt-redux-norm.perspective.scala
i18211.scala
i15743.scala

# Opaque type
i5720.scala
Expand Down
442 changes: 442 additions & 0 deletions library/src-bootstrapped/scala/Tuple.scala

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// non-bootstrapped version of Tuple.scala

package scala

import annotation.{experimental, showAsInfix}
Expand Down
12 changes: 8 additions & 4 deletions library/src/scala/runtime/Tuples.scala
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,8 @@ object Tuples {
// Tail for Tuple1 to Tuple22
private def specialCaseTail(self: Tuple): Tuple = {
(self: Any) match {
case self: EmptyTuple =>
throw new NoSuchElementException("tail of empty tuple")
case self: Tuple1[?] =>
EmptyTuple
case self: Tuple2[?, ?] =>
Expand Down Expand Up @@ -352,7 +354,7 @@ object Tuples {
}
}

def tail(self: NonEmptyTuple): Tuple = (self: Any) match {
def tail(self: Tuple): Tuple = (self: Any) match {
case xxl: TupleXXL => xxlTail(xxl)
case _ => specialCaseTail(self)
}
Expand Down Expand Up @@ -514,6 +516,8 @@ object Tuples {
// Init for Tuple1 to Tuple22
private def specialCaseInit(self: Tuple): Tuple = {
(self: Any) match {
case self: EmptyTuple =>
throw new NoSuchElementException("init of empty tuple")
case _: Tuple1[?] =>
EmptyTuple
case self: Tuple2[?, ?] =>
Expand Down Expand Up @@ -561,16 +565,16 @@ object Tuples {
}
}

def init(self: NonEmptyTuple): Tuple = (self: Any) match {
def init(self: Tuple): Tuple = (self: Any) match {
case xxl: TupleXXL => xxlInit(xxl)
case _ => specialCaseInit(self)
}

def last(self: NonEmptyTuple): Any = (self: Any) match {
def last(self: Tuple): Any = (self: Any) match {
case self: Product => self.productElement(self.productArity - 1)
}

def apply(self: NonEmptyTuple, n: Int): Any =
def apply(self: Tuple, n: Int): Any =
self.productElement(n)

// Benchmarks showed that this is faster than doing (it1 zip it2).copyToArray(...)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package transformers

class InheritanceInformationTransformer(using DocContext) extends (Module => Module):
override def apply(original: Module): Module =
val subtypes = getSupertypes(original.rootPackage).groupMap(_(0))(_(1)).view.mapValues(_.distinct).toMap
val subtypes = getSupertypes(original.rootPackage).groupMap(_._1)(_._2).view.mapValues(_.distinct).toMap
original.updateMembers { m =>
val edges = getEdges(m.asLink.copy(kind = bareClasslikeKind(m.kind)), subtypes)
val st: Seq[LinkToType] = edges.map(_._1).distinct
Expand Down
4 changes: 2 additions & 2 deletions tests/neg/i13780-1.check
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
-- [E007] Type Mismatch Error: tests/neg/i13780-1.scala:38:24 ----------------------------------------------------------
-- [E007] Type Mismatch Error: tests/neg/i13780-1.scala:38:26 ----------------------------------------------------------
38 | case x: (h *: t) => x.head // error
| ^^^^^^
| Found: Tuple.Head[VS & h *: t]
| Found: Tuple.Head[VS & h *: t] & Tuple.Head[(x : VS & h *: t)]
| Required: h
|
| where: VS is a type in method foo with bounds <: Tuple
Expand Down
4 changes: 4 additions & 0 deletions tests/pos/Tuple_apply.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
def testTuple(tup: Tuple) = tup(0)
def testNonEmptyTuple(tup: NonEmptyTuple) = tup(0)
def testConsUnbound(tup: Any *: Tuple) = tup(0)
def testCons(tup: Any *: EmptyTuple) = tup(0)
3 changes: 3 additions & 0 deletions tests/pos/i12721.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
def bar(t: Any): Int = 1
def foo(t: AnyRef): Unit =
t.asInstanceOf[NonEmptyTuple].toList.map(bar)
8 changes: 8 additions & 0 deletions tests/pos/i16207.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import scala.compiletime.constValueTuple
import scala.deriving.Mirror.ProductOf

case class C(date: Int, time: Int)

inline def labelsOf[A](using p: ProductOf[A]): Tuple = constValueTuple[p.MirroredElemLabels]

val headers: List[String] = labelsOf[C].toList.map(_.toString)
18 changes: 9 additions & 9 deletions tests/run-staging/liftables.check
Original file line number Diff line number Diff line change
Expand Up @@ -69,22 +69,22 @@ scala.Tuple21.apply[scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala
scala.Tuple22.apply[scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int](1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22)
{
val x$1: scala.Int = 1
scala.Tuple22.apply[scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int](2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23).*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.Tuple$package.EmptyTuple]]]]]]]]]]]]]]]]]]]]]]](x$1)
scala.Tuple.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.Tuple$package.EmptyTuple]]]]]]]]]]]]]]]]]]]]]]](scala.Tuple22.apply[scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int](2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23))(x$1)
}
{
val x$1: scala.Int = 1
{
scala.Tuple.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.Tuple$package.EmptyTuple]]]]]]]]]]]]]]]]]]]]]]]]({
val `x$1₂`: scala.Int = 2
scala.Tuple22.apply[scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int](3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24).*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.Tuple$package.EmptyTuple]]]]]]]]]]]]]]]]]]]]]]](`x$1₂`)
}.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.Tuple$package.EmptyTuple]]]]]]]]]]]]]]]]]]]]]]]](x$1)
scala.Tuple.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.Tuple$package.EmptyTuple]]]]]]]]]]]]]]]]]]]]]]](scala.Tuple22.apply[scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int](3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24))(`x$1₂`)
})(x$1)
}
{
val x$1: scala.Int = 1
{
scala.Tuple.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.Tuple$package.EmptyTuple]]]]]]]]]]]]]]]]]]]]]]]]]({
val `x$1₂`: scala.Int = 2
{
scala.Tuple.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.Tuple$package.EmptyTuple]]]]]]]]]]]]]]]]]]]]]]]]({
val `x$1₃`: scala.Int = 3
scala.Tuple22.apply[scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int](4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25).*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.Tuple$package.EmptyTuple]]]]]]]]]]]]]]]]]]]]]]](`x$1₃`)
}.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.Tuple$package.EmptyTuple]]]]]]]]]]]]]]]]]]]]]]]](`x$1₂`)
}.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.Tuple$package.EmptyTuple]]]]]]]]]]]]]]]]]]]]]]]]](x$1)
scala.Tuple.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.*:[scala.Int, scala.Tuple$package.EmptyTuple]]]]]]]]]]]]]]]]]]]]]]](scala.Tuple22.apply[scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int, scala.Int](4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25))(`x$1₃`)
})(`x$1₂`)
})(x$1)
}
8 changes: 4 additions & 4 deletions tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ val experimentalDefinitionInLibrary = Set(
"scala.quoted.Quotes.reflectModule.TermParamClauseMethods.hasErasedArgs",

// New feature: reverse method on Tuple
"scala.Tuple.reverse", // can be stabilized in 3.5
"scala.Tuple$.Reverse", // can be stabilized in 3.5
"scala.Tuple$.ReverseOnto", // can be stabilized in 3.5
"scala.runtime.Tuples$.reverse", // can be stabilized in 3.5
"scala.Tuple$.reverse",
"scala.Tuple$.Reverse",
"scala.Tuple$.ReverseOnto",
"scala.runtime.Tuples$.reverse",
)


Expand Down
4 changes: 2 additions & 2 deletions tests/run/tuple-ops.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ 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 {
val r6: (Int, Int, Int) = a.map[(1, 2, 3), [t] =>> Int]([t] => (x: t) => x match {
case x: Int => x * x
case _ => ???
})

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[(1, 2, 3), [t] =>> (t, Foo[t])]( [t] => (x: t) => (x, Foo(x)) )

// More Zip
val t1: Int *: Long *: Tuple = (1, 2l, 100, 200)
Expand Down
2 changes: 1 addition & 1 deletion tests/run/tuples1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ object Test extends App {
def head2[X <: NonEmptyTuple](x: X): Tuple.Head[X] = x.head

val hd1: Int = head1(x3)
// Without an explicit type parameter type inferance infers Nothing here.
// Without an explicit type parameter type inference infers Nothing here.
val hd2: Int = head2[x3.type](x3)

def tail1(x: NonEmptyTuple): Tuple.Tail[x.type] = x.tail
Expand Down
Loading