From 62544e8da9416fa4c6516fb139fc3766ca74919e Mon Sep 17 00:00:00 2001 From: Eugene Flesselle Date: Thu, 4 Jul 2024 14:13:15 +0200 Subject: [PATCH 1/2] Fix isomorphism tests of `AndOrType`s under non-empty `BinderPairs` 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, comparison of MatchCases, and AndTypes. --- .../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 efb353c4050c..741ffd4fd79d 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -3544,6 +3544,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 { @@ -3589,6 +3591,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) @@ -3741,6 +3747,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) + 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 From 21fc03fedf5eeb4a08ab622373f32e0c4c55ec8d Mon Sep 17 00:00:00 2001 From: Eugene Flesselle Date: Thu, 4 Jul 2024 17:25:46 +0200 Subject: [PATCH 2/2] Update compiler/src/dotty/tools/dotc/core/Types.scala --- compiler/src/dotty/tools/dotc/core/Types.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 741ffd4fd79d..62880b14cdeb 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -3749,7 +3749,7 @@ object Types extends TypeUtils { } override protected def iso(that: Any, bs: BinderPairs) = that match - case that: OrType => tp1.equals(that.tp1, bs) && tp2.equals(that.tp2, bs) + case that: OrType => tp1.equals(that.tp1, bs) && tp2.equals(that.tp2, bs) && isSoft == that.isSoft case _ => false }