Skip to content

Commit c35d9c1

Browse files
Add toExprOfTuple method for tuples
1 parent f0f8241 commit c35d9c1

File tree

5 files changed

+49
-0
lines changed

5 files changed

+49
-0
lines changed

compiler/test/dotc/pos-test-pickling.blacklist

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,6 @@ matchtype.scala
2424

2525
# Opaque type
2626
i5720.scala
27+
28+
# Tuples
29+
toexproftuple.scala

library/src-bootstrapped/scala/quoted/package.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,10 @@ package object quoted {
9797
}
9898
}
9999

100+
def (tup: T) toExprOfTuple[T <: Tuple: Tuple.IsInverseMap[Expr]] given (
101+
ctx: QuoteContext, t: Type[Tuple.InverseMap[T, Expr]]): Expr[Tuple.InverseMap[T, Expr]] = {
102+
import ctx.tasty._
103+
val res: Expr[Tuple] = tup.asInstanceOf[Product].productIterator.toSeq.asInstanceOf[Seq[Expr[_]]].toExprOfTuple
104+
res.cast[Tuple.InverseMap[T, Expr]]
105+
}
100106
}

library/src/scala/Tuple.scala

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,27 @@ object Tuple {
7474
case h *: t => F[h] *: Map[t, F]
7575
}
7676

77+
/** Converts a tuple `(F[T1], ..., F[Tn])` to `(T1, ... Tn)` */
78+
type InverseMap[X <: Tuple, F[_]] <: Tuple = X match {
79+
case F[x] *: t => x *: InverseMap[t, F]
80+
case Unit => Unit
81+
}
82+
type IsInverseMap[F[_]] = [X <: Tuple] =>> Tuple.IsInverseMap.PredicateAux[X, F, InverseMap[X, F]]
83+
object IsInverseMap {
84+
sealed trait Predicate[X <: Tuple, F[_]] { type Result <: Tuple }
85+
type PredicateAux[X <: Tuple, F[_], R] = Predicate[X, F] { type Result = R }
86+
87+
given [X <: NonEmptyTuple, F[_], H, T <: Tuple] as PredicateAux[X, F, H *: T] given (
88+
e1: Head[X] =:= F[H],
89+
e2: PredicateAux[Tail[X], F, T]) = new Predicate[X, F] {
90+
type Result = H *: T
91+
}
92+
93+
given [F[_]] as PredicateAux[Unit, F, Unit] = new Predicate[Unit, F] {
94+
type Result = Unit
95+
}
96+
}
97+
7798
/** Convert an array into a tuple of unknown arity and types */
7899
def fromArray[T](xs: Array[T]): Tuple = {
79100
val xs2 = xs match {

tests/neg/toexproftuple.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import scala.quoted._, scala.deriving._
2+
import given scala.quoted._
3+
4+
inline def mcr: Any = ${mcrImpl}
5+
def mcrImpl given (ctx: QuoteContext): Expr[Any] = {
6+
val tpl: (Expr[1], Expr[2], Expr[3]) = ('{1}, '{2}, '{3})
7+
'{val res: (1, 3, 3) = ${tpl.toExprOfTuple}; res} // error
8+
9+
val tpl2: (Expr[1], 2, Expr[3]) = ('{1}, 2, '{3})
10+
'{val res = ${tpl2.toExprOfTuple}; res} // error
11+
}

tests/pos/toexproftuple.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import scala.quoted._, scala.deriving._
2+
import given scala.quoted._
3+
4+
inline def mcr: Any = ${mcrImpl}
5+
def mcrImpl given (ctx: QuoteContext): Expr[Any] = {
6+
val tpl: (Expr[1], Expr[2], Expr[3]) = ('{1}, '{2}, '{3})
7+
'{val res: (1, 2, 3) = ${tpl.toExprOfTuple}; res}
8+
}

0 commit comments

Comments
 (0)