Skip to content

Commit 1431be2

Browse files
authored
Merge pull request #9565 from dotty-staging/fix-9473
Fix #9473: Add test
2 parents 6865160 + 3f8131f commit 1431be2

File tree

2 files changed

+62
-3
lines changed

2 files changed

+62
-3
lines changed

docs/docs/reference/contextual/derivation.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,15 +262,15 @@ object Eq {
262262

263263
def iterator[T](p: T) = p.asInstanceOf[Product].productIterator
264264

265-
def eqSum[T](s: Mirror.SumOf[T], elems: List[Eq[_]]): Eq[T] =
265+
def eqSum[T](s: Mirror.SumOf[T], elems: => List[Eq[_]]): Eq[T] =
266266
new Eq[T] {
267267
def eqv(x: T, y: T): Boolean = {
268268
val ordx = s.ordinal(x)
269269
(s.ordinal(y) == ordx) && check(elems(ordx))(x, y)
270270
}
271271
}
272272

273-
def eqProduct[T](p: Mirror.ProductOf[T], elems: List[Eq[_]]): Eq[T] =
273+
def eqProduct[T](p: Mirror.ProductOf[T], elems: => List[Eq[_]]): Eq[T] =
274274
new Eq[T] {
275275
def eqv(x: T, y: T): Boolean =
276276
iterator(x).zip(iterator(y)).zip(elems.iterator).forall {
@@ -279,7 +279,7 @@ object Eq {
279279
}
280280

281281
inline given derived[T](using m: Mirror.Of[T]) as Eq[T] = {
282-
val elemInstances = summonAll[m.MirroredElemTypes]
282+
lazy val elemInstances = summonAll[m.MirroredElemTypes]
283283
inline m match {
284284
case s: Mirror.SumOf[T] => eqSum(s, elemInstances)
285285
case p: Mirror.ProductOf[T] => eqProduct(p, elemInstances)

tests/run/i9473.scala

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import scala.deriving._
2+
import scala.compiletime.{erasedValue, summonInline}
3+
4+
inline def summonAll[T <: Tuple]: List[Eq[_]] = inline erasedValue[T] match {
5+
case _: EmptyTuple => Nil
6+
case _: (t *: ts) => summonInline[Eq[t]] :: summonAll[ts]
7+
}
8+
9+
trait Eq[T] {
10+
def eqv(x: T, y: T): Boolean
11+
}
12+
13+
object Eq {
14+
given Eq[Int] {
15+
def eqv(x: Int, y: Int) = x == y
16+
}
17+
18+
def check(elem: Eq[_])(x: Any, y: Any): Boolean =
19+
elem.asInstanceOf[Eq[Any]].eqv(x, y)
20+
21+
def iterator[T](p: T) = p.asInstanceOf[Product].productIterator
22+
23+
def eqSum[T](s: Mirror.SumOf[T], elems: => List[Eq[_]]): Eq[T] =
24+
new Eq[T] {
25+
def eqv(x: T, y: T): Boolean = {
26+
val ordx = s.ordinal(x)
27+
(s.ordinal(y) == ordx) && check(elems(ordx))(x, y)
28+
}
29+
}
30+
31+
def eqProduct[T](p: Mirror.ProductOf[T], elems: => List[Eq[_]]): Eq[T] =
32+
new Eq[T] {
33+
def eqv(x: T, y: T): Boolean =
34+
iterator(x).zip(iterator(y)).zip(elems.iterator).forall {
35+
case ((x, y), elem) => check(elem)(x, y)
36+
}
37+
}
38+
39+
inline given derived[T](using m: Mirror.Of[T]) as Eq[T] = {
40+
lazy val elemInstances = summonAll[m.MirroredElemTypes]
41+
inline m match {
42+
case s: Mirror.SumOf[T] => eqSum(s, elemInstances)
43+
case p: Mirror.ProductOf[T] => eqProduct(p, elemInstances)
44+
}
45+
}
46+
}
47+
48+
enum Tree[T] derives Eq {
49+
case Branch(left: Tree[T], right: Tree[T])
50+
case Leaf(elem: T)
51+
}
52+
53+
@main
54+
def Test = {
55+
import Tree._
56+
57+
val t1 = Branch(Leaf(1), Leaf(1))
58+
assert(summon[Eq[Tree[Int]]].eqv(t1, t1))
59+
}

0 commit comments

Comments
 (0)