Skip to content

Commit 7f095e9

Browse files
EugeneFlesselleWojciechMazur
authored andcommitted
Fix isomorphism tests of AndOrTypes under non-empty BinderPairs (#21017)
Before the changes, when comparing two `HKTypeLambda` result types, the list of binding pairs was lost when entering comparison of `AndOrType`s, which caused the `equals` to fail, and hence prevented hash-consing. Even though `M1` and `M2` in pos/i20858-min should still conform to one-another, we entered a deep-subtype comparison because of the order in which the TypeComparer does dealiasing of AppliedTypes, and comparison of MatchCases and AndTypes. Fix #20858 [Cherry-picked f2829c3]
1 parent bfe4871 commit 7f095e9

File tree

4 files changed

+49
-0
lines changed

4 files changed

+49
-0
lines changed

compiler/src/dotty/tools/dotc/core/Types.scala

+10
Original file line numberDiff line numberDiff line change
@@ -3540,6 +3540,8 @@ object Types extends TypeUtils {
35403540
else this match
35413541
case tp: OrType => OrType.make(tp1, tp2, tp.isSoft)
35423542
case tp: AndType => AndType.make(tp1, tp2, checkValid = true)
3543+
3544+
override def hashIsStable: Boolean = tp1.hashIsStable && tp2.hashIsStable
35433545
}
35443546

35453547
abstract case class AndType(tp1: Type, tp2: Type) extends AndOrType {
@@ -3585,6 +3587,10 @@ object Types extends TypeUtils {
35853587
case that: AndType => tp1.eq(that.tp1) && tp2.eq(that.tp2)
35863588
case _ => false
35873589
}
3590+
3591+
override protected def iso(that: Any, bs: BinderPairs) = that match
3592+
case that: AndType => tp1.equals(that.tp1, bs) && tp2.equals(that.tp2, bs)
3593+
case _ => false
35883594
}
35893595

35903596
final class CachedAndType(tp1: Type, tp2: Type) extends AndType(tp1, tp2)
@@ -3736,6 +3742,10 @@ object Types extends TypeUtils {
37363742
case that: OrType => tp1.eq(that.tp1) && tp2.eq(that.tp2) && isSoft == that.isSoft
37373743
case _ => false
37383744
}
3745+
3746+
override protected def iso(that: Any, bs: BinderPairs) = that match
3747+
case that: OrType => tp1.equals(that.tp1, bs) && tp2.equals(that.tp2, bs) && isSoft == that.isSoft
3748+
case _ => false
37393749
}
37403750

37413751
final class CachedOrType(tp1: Type, tp2: Type, override val isSoft: Boolean) extends OrType(tp1, tp2)

tests/pos/i20858-min.scala

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
type M[F[_,_]] = Int match
3+
case 0 => String & M[F]
4+
5+
type M1 = M[[x,y] =>> x | y]
6+
type M2 = M[[x,y] =>> x | y]
7+
8+
def Test: Unit =
9+
val x: M1 = ???
10+
val _: M2 = x // was error

tests/pos/i20858/defns_1.scala

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import scala.compiletime.*
2+
import scala.deriving.*
3+
4+
sealed trait ZIO[-R, +E, +A]
5+
sealed abstract class ZLayer[-RIn, +E, +ROut]
6+
object ZLayer:
7+
def apply[RIn, E, ROut](zio: => ZIO[RIn, E, ROut]): ZLayer[RIn, E, ROut] = ???
8+
type URIO[-R, +A] = ZIO[R, Nothing, A]
9+
type IAnyType[T <: Tuple] = Tuple.Fold[T, Any, [x, y] =>> x & y]
10+
type UAnyType[T <: Tuple] = Tuple.Fold[T, Any, [x, y] =>> x | y]
11+
12+
13+
trait AutoLayer[A]:
14+
def zlayer(using
15+
p: Mirror.ProductOf[A]
16+
): ZLayer[IAnyType[p.MirroredElemTypes], Nothing, A]
17+
18+
object AutoLayer:
19+
inline given derived[A](using p: Mirror.ProductOf[A]): AutoLayer[A] = {
20+
val a: ZIO[IAnyType[p.MirroredElemTypes], Nothing, A] = ???
21+
new AutoLayer[A]:
22+
override def zlayer(using
23+
pp: Mirror.ProductOf[A]
24+
): ZLayer[IAnyType[pp.MirroredElemTypes], Nothing, A] = ZLayer {
25+
a.asInstanceOf[ZIO[IAnyType[pp.MirroredElemTypes], Nothing, A]]
26+
}
27+
}

tests/pos/i20858/usages_2.scala

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
case class TestService(port: Int) derives AutoLayer // was error

0 commit comments

Comments
 (0)