Skip to content

Commit 0eecd60

Browse files
update test with derivation of migration
1 parent 67ad1f6 commit 0eecd60

File tree

1 file changed

+29
-33
lines changed

1 file changed

+29
-33
lines changed

tests/run/typeclass-derivation-defaultArgument.scala

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
import scala.deriving.Mirror as M
12
import scala.deriving.*
23
import scala.Tuple.*
34
import scala.compiletime.*
45
import scala.compiletime.ops.int.S
56

6-
trait Migration[From, To]:
7+
trait Migration[-From, +To]:
78
def apply(x: From): To
89

910
object Migration:
@@ -14,62 +15,56 @@ object Migration:
1415
given[T]: Migration[T, T] with
1516
override def apply(x: T): T = x
1617

17-
private type IndexOf[Elems <: Tuple, X] <: Int = Elems match {
18-
case (elem *: elems) =>
19-
elem match {
20-
case X => 0
21-
case _ => S[IndexOf[elems, X]]
22-
}
18+
type IndexOf[Elems <: Tuple, X] <: Int = Elems match {
19+
case (X *: elems) => 0
20+
case (_ *: elems) => S[IndexOf[elems, X]]
2321
case EmptyTuple => Nothing
2422
}
2523

26-
private inline def migrate[F,T](x: F): T = summonFrom {
27-
case migration: Migration[F,T] => migration(x)
28-
}
24+
inline def migrateElem[F,T, ToIdx <: Int](from: M.ProductOf[F], to: M.ProductOf[T])(x: Product): Any =
2925

30-
private inline def migrateElem[F,T, ToIdx <: Int]
31-
(from: Mirror.ProductOf[F], to: Mirror.ProductOf[T])
32-
(x: Product): Any =
3326
type Label = Elem[to.MirroredElemLabels, ToIdx]
3427
type FromIdx = IndexOf[from.MirroredElemLabels, Label]
3528
inline constValueOpt[FromIdx] match
29+
3630
case Some(fromIdx) =>
3731
type FromType = Elem[from.MirroredElemTypes, FromIdx]
3832
type ToType = Elem[to.MirroredElemTypes, ToIdx]
39-
val elem = x.productElement(fromIdx).asInstanceOf[FromType]
40-
migrate[FromType, ToType](elem)
33+
summonFrom { case _: Migration[FromType, ToType] =>
34+
x.productElement(fromIdx).asInstanceOf[FromType].migrateTo[ToType]
35+
}
36+
4137
case None =>
42-
type HasDefault = Elem[to.MirroredElemHasDefaults, ToIdx] // NOTE when are the annotations checked ?? bug expr is not checked for match types
38+
type HasDefault = Elem[to.MirroredElemHasDefaults, ToIdx]
4339
inline erasedValue[HasDefault] match
4440
case _: true => to.defaultArgument(constValue[ToIdx])
45-
case _: false => compiletime.error("An element has no equivalent in source or default")
46-
end migrateElem
41+
case _: false => compiletime.error("An element has no equivalent or default")
4742

48-
private inline def migrateElems[F,T, ToIdx <: Int]
49-
(from: Mirror.ProductOf[F], to: Mirror.ProductOf[T])
50-
(x: Product): Seq[Any] =
43+
44+
inline def migrateElems[F,T, ToIdx <: Int](from: M.ProductOf[F], to: M.ProductOf[T])(x: Product): Seq[Any] =
5145
inline erasedValue[ToIdx] match
5246
case _: Tuple.Size[to.MirroredElemLabels] => Seq()
5347
case _ => migrateElem[F,T,ToIdx](from, to)(x) +: migrateElems[F,T,S[ToIdx]](from, to)(x)
5448

55-
private inline def migrateProduct[F,T](from: Mirror.ProductOf[F], to: Mirror.ProductOf[T])
56-
(x: Product): T =
57-
val elems = migrateElems[F,T,0](from, to)(x)
49+
inline def migrateProduct[F,T](from: M.ProductOf[F], to: M.ProductOf[T])
50+
(x: Product): T =
51+
val elems = migrateElems[F, T, 0](from, to)(x)
5852
to.fromProduct(new Product:
59-
override def canEqual(that: Any): Boolean = false
60-
override def productArity: Int = x.productArity
61-
override def productElement(n: Int): Any = elems(n)
53+
def canEqual(that: Any): Boolean = false
54+
def productArity: Int = elems.length
55+
def productElement(n: Int): Any = elems(n)
6256
)
6357

64-
implicit inline def migration[F,T](using from: Mirror.Of[F], to: Mirror.Of[T]): Migration[F,T] =
65-
new Migration[F,T]:
66-
override def apply(x: F): T = inline from match
67-
case fromP: Mirror.ProductOf[F] => inline to match
68-
case _: Mirror.SumOf[T] => compiletime.error("Can not migrate a product to a sum")
69-
case toP: Mirror.ProductOf[T] => migrateProduct[F, T](fromP, toP)(x.asInstanceOf[Product])
58+
inline def migration[F,T](using from: M.Of[F], to: M.Of[T]): Migration[F,T] = (x: F) =>
59+
inline from match
60+
case fromP: M.ProductOf[F] => inline to match
61+
case toP: M.ProductOf[T] => migrateProduct[F, T](fromP, toP)(x.asInstanceOf[Product])
62+
case _: M.SumOf[T] => compiletime.error("Cannot migrate sums")
63+
case _: M.SumOf[F] => compiletime.error("Cannot migrate sums")
7064

7165
end Migration
7266

67+
7368
import Migration.*
7469
object Test extends App:
7570

@@ -98,6 +93,7 @@ object Test extends App:
9893
given Migration[E1, E2] = migration
9994
assert(E1(D1(1), D1(2)).migrateTo[E2] == E2(D2(true, 2), "hi", D2(true, 1)))
10095

96+
// should only use default when needed
10197
case class F1(x: Int)
10298
case class F2(x: Int = 3)
10399
given Migration[F1, F2] = migration

0 commit comments

Comments
 (0)