diff --git a/library/src/scala/deriving/Helpers.scala b/library/src/scala/deriving/Helpers.scala index 67f8dabcfa04..02404ee50cc8 100644 --- a/library/src/scala/deriving/Helpers.scala +++ b/library/src/scala/deriving/Helpers.scala @@ -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 @@ -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] diff --git a/tests/disabled/pos-macros/i7853/JsonEncoder_1.scala b/tests/disabled/pos-macros/i7853/JsonEncoder_1.scala index 856a6b3964b5..d37c84b861ad 100644 --- a/tests/disabled/pos-macros/i7853/JsonEncoder_1.scala +++ b/tests/disabled/pos-macros/i7853/JsonEncoder_1.scala @@ -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 } @@ -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 => @@ -45,4 +46,4 @@ object JsonEncoder { given stringEncoder as JsonEncoder[String] { def encode(value: String) = value } -} \ No newline at end of file +} diff --git a/tests/pos-special/typeclass-scaling.scala b/tests/pos-special/typeclass-scaling.scala index 1c9c38dc0534..6102e346136b 100644 --- a/tests/pos-special/typeclass-scaling.scala +++ b/tests/pos-special/typeclass-scaling.scala @@ -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 => @@ -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]) } } @@ -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 => } @@ -288,7 +286,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 => @@ -296,10 +294,10 @@ object typeclasses { 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 => } @@ -307,11 +305,15 @@ object typeclasses { 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) + }) } } @@ -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 { @@ -391,4 +393,4 @@ object Test extends App { implicitly[Pickler[E14[Int]]] implicitly[Pickler[E15[Int]]] implicitly[Pickler[E16[Int]]] -} \ No newline at end of file +} diff --git a/tests/run/deriving.scala b/tests/run/deriving.scala index 0eff2a2dc8a6..4e37a2e62f3a 100644 --- a/tests/run/deriving.scala +++ b/tests/run/deriving.scala @@ -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) @@ -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] => diff --git a/tests/run/typeclass-derivation3.scala b/tests/run/typeclass-derivation3.scala index d2e56735445e..675faab8da5d 100644 --- a/tests/run/typeclass-derivation3.scala +++ b/tests/run/typeclass-derivation3.scala @@ -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 => @@ -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]) } } @@ -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 => } @@ -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 => @@ -119,10 +117,10 @@ 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 => } @@ -130,11 +128,15 @@ object typeclasses { 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) + }) } } @@ -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 { @@ -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 => @@ -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(", ", ", ")") } }