Skip to content

Commit

Permalink
Merge pull request #14114 from mpilquist/topic/mirror-from-product-typed
Browse files Browse the repository at this point in the history
Add typed versions of Mirror.ProductOf#fromProduct
  • Loading branch information
TheElectronWill committed Feb 28, 2022
2 parents 5109909 + 6e6e0d2 commit fdf36a0
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 1 deletion.
11 changes: 11 additions & 0 deletions library/src/scala/deriving/Mirror.scala
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,15 @@ object Mirror {
type Of[T] = Mirror { type MirroredType = T; type MirroredMonoType = T ; type MirroredElemTypes <: Tuple }
type ProductOf[T] = Mirror.Product { type MirroredType = T; type MirroredMonoType = T ; type MirroredElemTypes <: Tuple }
type SumOf[T] = Mirror.Sum { type MirroredType = T; type MirroredMonoType = T; type MirroredElemTypes <: Tuple }

extension [T](p: ProductOf[T])
/** Create a new instance of type `T` with elements taken from product `a`. */
@annotation.experimental
def fromProductTyped[A <: scala.Product, Elems <: p.MirroredElemTypes](a: A)(using m: ProductOf[A] { type MirroredElemTypes = Elems }): T =
p.fromProduct(a)

/** Create a new instance of type `T` with elements taken from tuple `t`. */
@annotation.experimental
def fromTuple(t: p.MirroredElemTypes): T =
p.fromProduct(t)
}
2 changes: 2 additions & 0 deletions project/MiMaFilters.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ object MiMaFilters {
ProblemFilters.exclude[MissingClassProblem]("scala.compiletime.ops.long$"),
ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule#CompilationInfoModule.XmacroSettings"),
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.quoted.Quotes#reflectModule#CompilationInfoModule.XmacroSettings"),
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.deriving.Mirror.fromProductTyped"),
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.deriving.Mirror.fromTuple"),

// Private to the compiler - needed for forward binary compatibility
ProblemFilters.exclude[MissingClassProblem]("scala.annotation.since")
Expand Down
10 changes: 10 additions & 0 deletions tests/neg/deriving-from-product-typed.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import deriving.Mirror

case class A(x: Int, y: String)
case class B(a: Any, b: Any)
object A:
def f = summon[Mirror.ProductOf[A]].fromProductTyped((1, 2)) // error
def g = summon[Mirror.ProductOf[A]].fromTuple((1, 2)) // error
def h = summon[Mirror.ProductOf[B]].fromProductTyped(A(1, ""))
def i = summon[Mirror.ProductOf[A]].fromProductTyped(B(1, "")) // error

2 changes: 1 addition & 1 deletion tests/neg/deriving.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ sealed trait B derives Generic // error: cannot take shape, its subclass class D

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


class E derives Generic // error: cannot take shape, it is neither sealed nor a case class

sealed trait F derives Generic // error: cannot take shape, it has anonymous or inaccessible subclasses
Expand All @@ -23,3 +22,4 @@ object G {
case class H() extends F
}
}

11 changes: 11 additions & 0 deletions tests/run/deriving-from-product-typed.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
case class A(x: Option[Int], y: Option[Any])
case class B(x: Some[Int], y: Some[Boolean])

object Test extends App:
import deriving.*

val ma = summon[Mirror.ProductOf[A]]

ma.fromProductTyped(B(Some(1), Some(true)))
ma.fromProductTyped((Some(1), Some(false)))

2 changes: 2 additions & 0 deletions tests/run/deriving.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ object Test extends App {
case class AA[X >: Null <: AnyRef](x: X, y: X, z: String)

println(summon[Mirror.ProductOf[A]].fromProduct(A(1, 2)))
summon[Mirror.ProductOf[A]].fromProductTyped(A(1, 2))
summon[Mirror.ProductOf[A]].fromTuple((1, 2))
assert(summon[Mirror.SumOf[T]].ordinal(A(1, 2)) == 0)
assert(summon[Mirror.Sum { type MirroredType = T }].ordinal(B) == 1)
summon[Mirror.Of[A]] match {
Expand Down

0 comments on commit fdf36a0

Please sign in to comment.