From 19ae73b8430dfe613e17c77def8c0c91943db947 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 3 Oct 2021 15:05:50 +0200 Subject: [PATCH 1/2] Remember compared polytypes Remember comparisons of PolyTypes in `comparedTypeLambdas`. This means that parameters of such types will not be added to the constraint. We already do the same for HkTypeLambdas but for some reason we forgot to do it for PolyTypes, which are the other kind of type lambdas. Fixes #13660 Allows perspective to be re-enabled in CB --- .../communitybuild/CommunityBuildTest.scala | 2 +- .../dotty/tools/dotc/core/TypeComparer.scala | 24 ++++++++++++------- tests/pos/i13660.scala | 15 ++++++++++++ 3 files changed, 31 insertions(+), 10 deletions(-) create mode 100644 tests/pos/i13660.scala diff --git a/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala b/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala index 7b182133e78e..c1d748b4d3ad 100644 --- a/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala +++ b/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala @@ -45,7 +45,7 @@ class CommunityBuildTestB: @Test def fs2 = projects.fs2.run() @Test def munit = projects.munit.run() @Test def munitCatsEffect = projects.munitCatsEffect.run() - // @Test def perspective = projects.perspective.run() + @Test def perspective = projects.perspective.run() @Test def scalacheckEffect = projects.scalacheckEffect.run() @Test def scodec = projects.scodec.run() @Test def scodecBits = projects.scodecBits.run() diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 49cfb2b6191c..daa7394dae52 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -184,6 +184,12 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling val bounds = gadtBounds(sym) bounds != null && op(bounds) + private inline def comparingTypeLambdas(tl1: TypeLambda, tl2: TypeLambda)(op: => Boolean): Boolean = + val saved = comparedTypeLambdas + comparedTypeLambdas += tl1 + comparedTypeLambdas += tl2 + try op finally comparedTypeLambdas = saved + protected def isSubType(tp1: Type, tp2: Type, a: ApproxState): Boolean = { val savedApprox = approx val savedLeftRoot = leftRoot @@ -629,12 +635,10 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling migrateTo3 || tp1.typeParams.corresponds(tp2.typeParams)((tparam1, tparam2) => isSubType(tparam2.paramInfo.subst(tp2, tp1), tparam1.paramInfo)) - val saved = comparedTypeLambdas - comparedTypeLambdas += tp1 - comparedTypeLambdas += tp2 - val variancesOK = variancesConform(tp1.typeParams, tp2.typeParams) - try variancesOK && boundsOK && isSubType(tp1.resType, tp2.resType.subst(tp2, tp1)) - finally comparedTypeLambdas = saved + comparingTypeLambdas(tp1, tp2) { + val variancesOK = variancesConform(tp1.typeParams, tp2.typeParams) + variancesOK && boundsOK && isSubType(tp1.resType, tp2.resType.subst(tp2, tp1)) + } case _ => val tparams1 = tp1.typeParams if (tparams1.nonEmpty) @@ -704,9 +708,11 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling case tp2: PolyType => def comparePoly = tp1 match { case tp1: PolyType => - (tp1.signature consistentParams tp2.signature) && - matchingPolyParams(tp1, tp2) && - isSubType(tp1.resultType, tp2.resultType.subst(tp2, tp1)) + comparingTypeLambdas(tp1, tp2) { + (tp1.signature consistentParams tp2.signature) + && matchingPolyParams(tp1, tp2) + && isSubType(tp1.resultType, tp2.resultType.subst(tp2, tp1)) + } case _ => false } comparePoly diff --git a/tests/pos/i13660.scala b/tests/pos/i13660.scala new file mode 100644 index 000000000000..328a82d0e560 --- /dev/null +++ b/tests/pos/i13660.scala @@ -0,0 +1,15 @@ +type Const[A] = [_] =>> A +type FunctionK[A[_], B[_]] = [Z] => A[Z] => B[Z] + +type #~>#:[T, R] = FunctionK[Const[T], Const[R]] + +object FunctionK: + def liftConst[A, B](f: A => B): /*FunctionK[Const[A], Const[B]]*/ A #~>#: B = + [Z1] => (a: A) => f(a) + +trait FoldableK[F[_[_], _]]: + + def foldMapK1[A[_], C, B](fa: F[A, C])(f: FunctionK[A, Const[B]]): B + + def toListK[A, C](fa: F[Const[A], C]): List[A] = + foldMapK1(fa)(FunctionK.liftConst(List(_: A))) From 45c7d6857a1bd80546367a7152e7d378e53e3904 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 3 Oct 2021 18:17:34 +0200 Subject: [PATCH 2/2] Regression test for #7888 --- tests/pos/i7888.scala | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tests/pos/i7888.scala diff --git a/tests/pos/i7888.scala b/tests/pos/i7888.scala new file mode 100644 index 000000000000..d188bb23e72e --- /dev/null +++ b/tests/pos/i7888.scala @@ -0,0 +1,8 @@ +def usingSeq[B](f: [A] => Seq[A] => B): B = { + f(Nil) +} +def crash() = { + usingSeq { [A] => (a: Seq[A]) => + a + } +}