Skip to content

Commit 8fefb76

Browse files
committed
Add typed versions of Mirror.ProductOf#fromProduct
1 parent 7bf25f5 commit 8fefb76

File tree

3 files changed

+27
-5
lines changed

3 files changed

+27
-5
lines changed

library/src/scala/deriving/Mirror.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,13 @@ object Mirror {
4949
type Of[T] = Mirror { type MirroredType = T; type MirroredMonoType = T ; type MirroredElemTypes <: Tuple }
5050
type ProductOf[T] = Mirror.Product { type MirroredType = T; type MirroredMonoType = T ; type MirroredElemTypes <: Tuple }
5151
type SumOf[T] = Mirror.Sum { type MirroredType = T; type MirroredMonoType = T; type MirroredElemTypes <: Tuple }
52+
53+
extension [T](p: ProductOf[T])
54+
/** Create a new instance of type `T` with elements taken from product `a`. */
55+
def fromProductTyped[A <: scala.Product](a: A)(using m: ProductOf[A], ev: p.MirroredElemTypes =:= m.MirroredElemTypes): T =
56+
p.fromProduct(a)
57+
58+
/** Create a new instance of type `T` with elements taken from tuple `t`. */
59+
def fromTuple(t: p.MirroredElemTypes): T =
60+
p.fromProduct(t)
5261
}

tests/neg/deriving.scala

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import reflect.Generic
1+
import deriving.MirrorOf
22

3-
sealed trait A derives Generic // error: cannot take shape, it has anonymous or inaccessible subclasses
3+
sealed trait A
44

55
object A {
66
def f() = {
@@ -9,17 +9,28 @@ object A {
99
}
1010
}
1111

12-
sealed trait B derives Generic // error: cannot take shape, its subclass class D is not a case class
12+
def aMirror = summon[Mirror.Of[A]] // error: cannot take shape, it has anonymous or inaccessible subclasses
13+
14+
sealed trait B
1315

1416
class D(x: Int, y: String) extends B
1517

18+
def bMirror = summon[Mirror.Of[B]] // error: cannot take shape, its subclass class D is not a case class
1619

17-
class E derives Generic // error: cannot take shape, it is neither sealed nor a case class
20+
class E
21+
def eMirror = summon[Mirror.Of[E]] // error: cannot take shape, it is neither sealed nor a case class
1822

19-
sealed trait F derives Generic // error: cannot take shape, it has anonymous or inaccessible subclasses
23+
sealed trait F
24+
def fMirror = summon[Mirror.Of[F]] // error: cannot take shape, it has anonymous or inaccessible subclasses
2025

2126
object G {
2227
def f() = {
2328
case class H() extends F
2429
}
2530
}
31+
32+
case class I(x: Int, y: String)
33+
object I:
34+
def f = summon[deriving.Mirror.ProductOf[I]].fromProductTyped((1, 2)) // error
35+
def g = summon[deriving.Mirror.ProductOf[I]].fromTuple((1, 2)) // error
36+

tests/run/deriving.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ object Test extends App {
1313
case class AA[X >: Null <: AnyRef](x: X, y: X, z: String)
1414

1515
println(summon[Mirror.ProductOf[A]].fromProduct(A(1, 2)))
16+
summon[Mirror.ProductOf[A]].fromProductTyped(A(1, 2))
17+
summon[Mirror.ProductOf[A]].fromTuple((1, 2))
1618
assert(summon[Mirror.SumOf[T]].ordinal(A(1, 2)) == 0)
1719
assert(summon[Mirror.Sum { type MirroredType = T }].ordinal(B) == 1)
1820
summon[Mirror.Of[A]] match {

0 commit comments

Comments
 (0)