Skip to content

Deprecate the helpers in scala.deriving. #10436

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 1 commit into from
Nov 23, 2020
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
3 changes: 3 additions & 0 deletions library/src/scala/deriving/Helpers.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package scala.deriving

/** Helper class to turn arrays into products */
@deprecated("explicitly create a `new Product {...}` wrapper for the array or use `Tuple.fromArray`", "3.0.0-M2")
class ArrayProduct(val elems: Array[AnyRef]) extends Product {
def this(size: Int) = this(new Array[AnyRef](size))
def canEqual(that: Any): Boolean = true
Expand All @@ -11,8 +12,10 @@ class ArrayProduct(val elems: Array[AnyRef]) extends Product {
}

/** The empty product */
@deprecated("use EmptyTuple instead", "3.0.0-M2")
object EmptyProduct extends ArrayProduct(Array.emptyObjectArray)

/** Helper method to select a product element */
@deprecated("use x.asInstanceOf[Product].productElement(idx).asInstanceOf[T] instead", "3.0.0-M2")
def productElement[T](x: Any, idx: Int): T =
x.asInstanceOf[Product].productElement(idx).asInstanceOf[T]
11 changes: 6 additions & 5 deletions tests/disabled/pos-macros/i7853/JsonEncoder_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ object JsonEncoder {

inline def encodeElem[T](elem: T): String = summonInline[JsonEncoder[T]].encode(elem)

inline def encodeElems[Elems <: Tuple](idx: Int)(value: Any): List[String] =
inline def encodeElems[Elems <: Tuple](idx: Int)(value: Product): List[String] =
inline erasedValue[Elems] match {
case _: (elem *: elems1) =>
encodeElem[elem](productElement[elem](value, idx)) :: encodeElems[elems1](idx + 1)(value)
encodeElem[elem](value.productElement(idx).asInstanceOf[elem]) :: encodeElems[elems1](idx + 1)(value)
case _ => Nil
}

Expand All @@ -25,8 +25,9 @@ object JsonEncoder {
case m: Mirror.SumOf[T] =>
"not supporting this case yet"
case m: Mirror.ProductOf[T] =>
val elems = encodeElems[m.MirroredElemTypes](0)(value)
val labels = value.asInstanceOf[Product].productElementNames
val valueProduct = value.asInstanceOf[Product]
val elems = encodeElems[m.MirroredElemTypes](0)(valueProduct)
val labels = valueProduct.productElementNames
val keyValues = labels.zip(elems).map((k, v) => s"$k: $v")
"{" + (keyValues).mkString(", ") + "}"
case other =>
Expand All @@ -45,4 +46,4 @@ object JsonEncoder {
given stringEncoder as JsonEncoder[String] {
def encode(value: String) = value
}
}
}
36 changes: 19 additions & 17 deletions tests/pos-special/typeclass-scaling.scala
Original file line number Diff line number Diff line change
Expand Up @@ -220,24 +220,22 @@ object typeclasses {

inline def tryEql[TT](x: TT, y: TT): Boolean = summonInline[Eq[TT]].eql(x, y)

inline def eqlElems[Elems <: Tuple](n: Int)(x: Any, y: Any): Boolean =
inline def eqlElems[Elems <: Tuple](n: Int)(x: Product, y: Product): Boolean =
inline erasedValue[Elems] match {
case _: (elem *: elems1) =>
tryEql[elem](productElement[elem](x, n), productElement[elem](y, n)) &&
tryEql[elem](x.productElement(n).asInstanceOf[elem], y.productElement(n).asInstanceOf[elem]) &&
eqlElems[elems1](n + 1)(x, y)
case _: EmptyTuple =>
true
}

inline def eqlProduct[T](m: Mirror.ProductOf[T])(x: Any, y: Any): Boolean =
eqlElems[m.MirroredElemTypes](0)(x, y)

inline def eqlCases[Alts](n: Int)(x: Any, y: Any, ord: Int): Boolean =
inline erasedValue[Alts] match {
case _: (alt *: alts1) =>
if (ord == n)
summonFrom {
case m: Mirror.ProductOf[`alt`] => eqlElems[m.MirroredElemTypes](0)(x, y)
case m: Mirror.ProductOf[`alt`] =>
eqlElems[m.MirroredElemTypes](0)(x.asInstanceOf[Product], y.asInstanceOf[Product])
}
else eqlCases[alts1](n + 1)(x, y, ord)
case _: EmptyTuple =>
Expand All @@ -251,7 +249,7 @@ object typeclasses {
val ord = m.ordinal(x)
ord == m.ordinal(y) && eqlCases[m.MirroredElemTypes](0)(x, y, ord)
case m: Mirror.ProductOf[T] =>
eqlElems[m.MirroredElemTypes](0)(x, y)
eqlElems[m.MirroredElemTypes](0)(x.asInstanceOf[Product], y.asInstanceOf[Product])
}
}

Expand All @@ -275,10 +273,10 @@ object typeclasses {

inline def tryPickle[T](buf: mutable.ListBuffer[Int], x: T): Unit = summonInline[Pickler[T]].pickle(buf, x)

inline def pickleElems[Elems <: Tuple](n: Int)(buf: mutable.ListBuffer[Int], x: Any): Unit =
inline def pickleElems[Elems <: Tuple](n: Int)(buf: mutable.ListBuffer[Int], x: Product): Unit =
inline erasedValue[Elems] match {
case _: (elem *: elems1) =>
tryPickle[elem](buf, productElement[elem](x, n))
tryPickle[elem](buf, x.productElement(n).asInstanceOf[elem])
pickleElems[elems1](n + 1)(buf, x)
case _: EmptyTuple =>
}
Expand All @@ -288,30 +286,34 @@ object typeclasses {
case _: (alt *: alts1) =>
if (ord == n)
summonFrom {
case m: Mirror.ProductOf[`alt`] => pickleElems[m.MirroredElemTypes](0)(buf, x)
case m: Mirror.ProductOf[`alt`] => pickleElems[m.MirroredElemTypes](0)(buf, x.asInstanceOf[Product])
}
else pickleCases[alts1](n + 1)(buf, x, ord)
case _: EmptyTuple =>
}

inline def tryUnpickle[T](buf: mutable.ListBuffer[Int]): T = summonInline[Pickler[T]].unpickle(buf)

inline def unpickleElems[Elems <: Tuple](n: Int)(buf: mutable.ListBuffer[Int], elems: ArrayProduct): Unit =
inline def unpickleElems[Elems <: Tuple](n: Int)(buf: mutable.ListBuffer[Int], elems: Array[Any]): Unit =
inline erasedValue[Elems] match {
case _: (elem *: elems1) =>
elems(n) = tryUnpickle[elem](buf).asInstanceOf[AnyRef]
elems(n) = tryUnpickle[elem](buf)
unpickleElems[elems1](n + 1)(buf, elems)
case _: EmptyTuple =>
}

inline def unpickleCase[T, Elems <: Tuple](buf: mutable.ListBuffer[Int], m: Mirror.ProductOf[T]): T = {
inline val size = constValue[Tuple.Size[Elems]]
inline if (size == 0)
m.fromProduct(EmptyProduct)
m.fromProduct(EmptyTuple)
else {
val elems = new ArrayProduct(size)
val elems = new Array[Any](size)
unpickleElems[Elems](0)(buf, elems)
m.fromProduct(elems)
m.fromProduct(new Product {
def canEqual(that: Any): Boolean = true
def productArity: Int = size
def productElement(idx: Int): Any = elems(idx)
})
}
}

Expand All @@ -336,7 +338,7 @@ object typeclasses {
buf += ord
pickleCases[m.MirroredElemTypes](0)(buf, x, ord)
case m: Mirror.ProductOf[T] =>
pickleElems[m.MirroredElemTypes](0)(buf, x)
pickleElems[m.MirroredElemTypes](0)(buf, x.asInstanceOf[Product])
}
def unpickle(buf: mutable.ListBuffer[Int]): T =
inline ev match {
Expand Down Expand Up @@ -391,4 +393,4 @@ object Test extends App {
implicitly[Pickler[E14[Int]]]
implicitly[Pickler[E15[Int]]]
implicitly[Pickler[E16[Int]]]
}
}
4 changes: 2 additions & 2 deletions tests/run/deriving.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ sealed trait U
case class C() extends U

object Test extends App {
import deriving.{Mirror, EmptyProduct}
import deriving._

case class AA[X >: Null <: AnyRef](x: X, y: X, z: String)

Expand All @@ -21,7 +21,7 @@ object Test extends App {
}
summon[Mirror.Of[B.type]] match {
case m: Mirror.Product =>
println(m.fromProduct(EmptyProduct))
println(m.fromProduct(EmptyTuple))
}
summon[Mirror.Of[T]] match {
case m: Mirror.SumOf[T] =>
Expand Down
40 changes: 21 additions & 19 deletions tests/run/typeclass-derivation3.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,24 +39,22 @@ object typeclasses {
case eq: Eq[TT] => eq.eql(x, y)
}

inline def eqlElems[Elems <: Tuple](n: Int)(x: Any, y: Any): Boolean =
inline def eqlElems[Elems <: Tuple](n: Int)(x: Product, y: Product): Boolean =
inline erasedValue[Elems] match {
case _: (elem *: elems1) =>
tryEql[elem](productElement[elem](x, n), productElement[elem](y, n)) &&
tryEql[elem](x.productElement(n).asInstanceOf[elem], y.productElement(n).asInstanceOf[elem]) &&
eqlElems[elems1](n + 1)(x, y)
case _: EmptyTuple =>
true
}

inline def eqlProduct[T](m: Mirror.ProductOf[T])(x: Any, y: Any): Boolean =
eqlElems[m.MirroredElemTypes](0)(x, y)

inline def eqlCases[Alts](n: Int)(x: Any, y: Any, ord: Int): Boolean =
inline erasedValue[Alts] match {
case _: (alt *: alts1) =>
if (ord == n)
summonFrom {
case m: Mirror.ProductOf[`alt`] => eqlElems[m.MirroredElemTypes](0)(x, y)
case m: Mirror.ProductOf[`alt`] =>
eqlElems[m.MirroredElemTypes](0)(x.asInstanceOf[Product], y.asInstanceOf[Product])
}
else eqlCases[alts1](n + 1)(x, y, ord)
case _: EmptyTuple =>
Expand All @@ -70,7 +68,7 @@ object typeclasses {
val ord = m.ordinal(x)
ord == m.ordinal(y) && eqlCases[m.MirroredElemTypes](0)(x, y, ord)
case m: Mirror.ProductOf[T] =>
eqlElems[m.MirroredElemTypes](0)(x, y)
eqlElems[m.MirroredElemTypes](0)(x.asInstanceOf[Product], y.asInstanceOf[Product])
}
}

Expand All @@ -96,10 +94,10 @@ object typeclasses {
case pkl: Pickler[T] => pkl.pickle(buf, x)
}

inline def pickleElems[Elems <: Tuple](n: Int)(buf: mutable.ListBuffer[Int], x: Any): Unit =
inline def pickleElems[Elems <: Tuple](n: Int)(buf: mutable.ListBuffer[Int], x: Product): Unit =
inline erasedValue[Elems] match {
case _: (elem *: elems1) =>
tryPickle[elem](buf, productElement[elem](x, n))
tryPickle[elem](buf, x.productElement(n).asInstanceOf[elem])
pickleElems[elems1](n + 1)(buf, x)
case _: EmptyTuple =>
}
Expand All @@ -109,7 +107,7 @@ object typeclasses {
case _: (alt *: alts1) =>
if (ord == n)
summonFrom {
case m: Mirror.ProductOf[`alt`] => pickleElems[m.MirroredElemTypes](0)(buf, x)
case m: Mirror.ProductOf[`alt`] => pickleElems[m.MirroredElemTypes](0)(buf, x.asInstanceOf[Product])
}
else pickleCases[alts1](n + 1)(buf, x, ord)
case _: EmptyTuple =>
Expand All @@ -119,22 +117,26 @@ object typeclasses {
case pkl: Pickler[T] => pkl.unpickle(buf)
}

inline def unpickleElems[Elems <: Tuple](n: Int)(buf: mutable.ListBuffer[Int], elems: ArrayProduct): Unit =
inline def unpickleElems[Elems <: Tuple](n: Int)(buf: mutable.ListBuffer[Int], elems: Array[Any]): Unit =
inline erasedValue[Elems] match {
case _: (elem *: elems1) =>
elems(n) = tryUnpickle[elem](buf).asInstanceOf[AnyRef]
elems(n) = tryUnpickle[elem](buf)
unpickleElems[elems1](n + 1)(buf, elems)
case _: EmptyTuple =>
}

inline def unpickleCase[T, Elems <: Tuple](buf: mutable.ListBuffer[Int], m: Mirror.ProductOf[T]): T = {
inline val size = constValue[Tuple.Size[Elems]]
inline if (size == 0)
m.fromProduct(EmptyProduct)
m.fromProduct(EmptyTuple)
else {
val elems = new ArrayProduct(size)
val elems = new Array[Any](size)
unpickleElems[Elems](0)(buf, elems)
m.fromProduct(elems)
m.fromProduct(new Product {
def canEqual(that: Any): Boolean = true
def productArity: Int = size
def productElement(idx: Int): Any = elems(idx)
})
}
}

Expand All @@ -159,7 +161,7 @@ object typeclasses {
buf += ord
pickleCases[m.MirroredElemTypes](0)(buf, x, ord)
case m: Mirror.ProductOf[T] =>
pickleElems[m.MirroredElemTypes](0)(buf, x)
pickleElems[m.MirroredElemTypes](0)(buf, x.asInstanceOf[Product])
}
def unpickle(buf: mutable.ListBuffer[Int]): T =
inline ev match {
Expand Down Expand Up @@ -188,13 +190,13 @@ object typeclasses {

inline def tryShow[T](x: T): String = summonInline[Show[T]].show(x)

inline def showElems[Elems <: Tuple, Labels <: Tuple](n: Int)(x: Any): List[String] =
inline def showElems[Elems <: Tuple, Labels <: Tuple](n: Int)(x: Product): List[String] =
inline erasedValue[Elems] match {
case _: (elem *: elems1) =>
inline erasedValue[Labels] match {
case _: (label *: labels1) =>
val formal = constValue[label]
val actual = tryShow(productElement[elem](x, n))
val actual = tryShow(x.productElement(n).asInstanceOf[elem])
s"$formal = $actual" :: showElems[elems1, labels1](n + 1)(x)
}
case _: EmptyTuple =>
Expand All @@ -205,7 +207,7 @@ object typeclasses {
val label = constValue[m.MirroredLabel]
inline m match {
case m: Mirror.Singleton => label
case _ => showElems[m.MirroredElemTypes, m.MirroredElemLabels](0)(x).mkString(s"$label(", ", ", ")")
case _ => showElems[m.MirroredElemTypes, m.MirroredElemLabels](0)(x.asInstanceOf[Product]).mkString(s"$label(", ", ", ")")
}
}

Expand Down