Skip to content

Add typed versions of Mirror.ProductOf#fromProduct #14114

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

Merged
merged 5 commits into from
Feb 28, 2022
Merged
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
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