From 27fe00e9e19a1596f3ab40dfbec0747986832ab7 Mon Sep 17 00:00:00 2001 From: Eugene Flesselle Date: Thu, 4 Jul 2024 19:15:59 +0200 Subject: [PATCH] Fix isomorphism tests of `AndOrType`s 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 f2829c3fab28cc6ab47a5627abda855884476572] --- .../src/dotty/tools/dotc/core/Types.scala | 10 +++++++ tests/pos/i20858-min.scala | 10 +++++++ tests/pos/i20858/defns_1.scala | 27 +++++++++++++++++++ tests/pos/i20858/usages_2.scala | 2 ++ 4 files changed, 49 insertions(+) create mode 100644 tests/pos/i20858-min.scala create mode 100644 tests/pos/i20858/defns_1.scala create mode 100644 tests/pos/i20858/usages_2.scala diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 2d3027504936..4be905beefcc 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -3348,6 +3348,8 @@ object Types extends TypeUtils { else this match case tp: OrType => OrType.make(tp1, tp2, tp.isSoft) case tp: AndType => AndType.make(tp1, tp2, checkValid = true) + + override def hashIsStable: Boolean = tp1.hashIsStable && tp2.hashIsStable } abstract case class AndType(tp1: Type, tp2: Type) extends AndOrType { @@ -3393,6 +3395,10 @@ object Types extends TypeUtils { case that: AndType => tp1.eq(that.tp1) && tp2.eq(that.tp2) case _ => false } + + override protected def iso(that: Any, bs: BinderPairs) = that match + case that: AndType => tp1.equals(that.tp1, bs) && tp2.equals(that.tp2, bs) + case _ => false } final class CachedAndType(tp1: Type, tp2: Type) extends AndType(tp1, tp2) @@ -3542,6 +3548,10 @@ object Types extends TypeUtils { case that: OrType => tp1.eq(that.tp1) && tp2.eq(that.tp2) && isSoft == that.isSoft case _ => false } + + override protected def iso(that: Any, bs: BinderPairs) = that match + case that: OrType => tp1.equals(that.tp1, bs) && tp2.equals(that.tp2, bs) && isSoft == that.isSoft + case _ => false } final class CachedOrType(tp1: Type, tp2: Type, override val isSoft: Boolean) extends OrType(tp1, tp2) diff --git a/tests/pos/i20858-min.scala b/tests/pos/i20858-min.scala new file mode 100644 index 000000000000..9c47b04031e6 --- /dev/null +++ b/tests/pos/i20858-min.scala @@ -0,0 +1,10 @@ + +type M[F[_,_]] = Int match + case 0 => String & M[F] + +type M1 = M[[x,y] =>> x | y] +type M2 = M[[x,y] =>> x | y] + +def Test: Unit = + val x: M1 = ??? + val _: M2 = x // was error diff --git a/tests/pos/i20858/defns_1.scala b/tests/pos/i20858/defns_1.scala new file mode 100644 index 000000000000..7b4b84745b58 --- /dev/null +++ b/tests/pos/i20858/defns_1.scala @@ -0,0 +1,27 @@ +import scala.compiletime.* +import scala.deriving.* + +sealed trait ZIO[-R, +E, +A] +sealed abstract class ZLayer[-RIn, +E, +ROut] +object ZLayer: + def apply[RIn, E, ROut](zio: => ZIO[RIn, E, ROut]): ZLayer[RIn, E, ROut] = ??? +type URIO[-R, +A] = ZIO[R, Nothing, A] +type IAnyType[T <: Tuple] = Tuple.Fold[T, Any, [x, y] =>> x & y] +type UAnyType[T <: Tuple] = Tuple.Fold[T, Any, [x, y] =>> x | y] + + +trait AutoLayer[A]: + def zlayer(using + p: Mirror.ProductOf[A] + ): ZLayer[IAnyType[p.MirroredElemTypes], Nothing, A] + +object AutoLayer: + inline given derived[A](using p: Mirror.ProductOf[A]): AutoLayer[A] = { + val a: ZIO[IAnyType[p.MirroredElemTypes], Nothing, A] = ??? + new AutoLayer[A]: + override def zlayer(using + pp: Mirror.ProductOf[A] + ): ZLayer[IAnyType[pp.MirroredElemTypes], Nothing, A] = ZLayer { + a.asInstanceOf[ZIO[IAnyType[pp.MirroredElemTypes], Nothing, A]] + } + } \ No newline at end of file diff --git a/tests/pos/i20858/usages_2.scala b/tests/pos/i20858/usages_2.scala new file mode 100644 index 000000000000..3a05ba54e97a --- /dev/null +++ b/tests/pos/i20858/usages_2.scala @@ -0,0 +1,2 @@ + +case class TestService(port: Int) derives AutoLayer // was error