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))) 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 + } +}