Skip to content

Commit 926d5bd

Browse files
committed
fix i13146 - use fullyDefinedType
1 parent dacd2d5 commit 926d5bd

File tree

2 files changed

+55
-1
lines changed

2 files changed

+55
-1
lines changed

compiler/src/dotty/tools/dotc/typer/Synthesizer.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,8 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
540540
(using Context): TreeWithErrors =
541541
if checkFormal(formal) then
542542
formal.member(tpnme.MirroredType).info match
543-
case TypeBounds(mirroredType, _) => synth(TypeOps.stripTypeVars(mirroredType), formal, span)
543+
case TypeBounds(mirroredType, _) =>
544+
synth(fullyDefinedType(mirroredType, "Mirror.*Of argument", ctx.source.atSpan(span)), formal, span)
544545
case other => EmptyTreeNoError
545546
else EmptyTreeNoError
546547

tests/run/i13146.scala

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

0 commit comments

Comments
 (0)