Skip to content

Commit

Permalink
Merge pull request #13663 from dotty-staging/fix-13660
Browse files Browse the repository at this point in the history
Remember compared polytypes
  • Loading branch information
smarter authored Oct 4, 2021
2 parents 85d444e + 45c7d68 commit 9ecacb1
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
24 changes: 15 additions & 9 deletions compiler/src/dotty/tools/dotc/core/TypeComparer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
15 changes: 15 additions & 0 deletions tests/pos/i13660.scala
Original file line number Diff line number Diff line change
@@ -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)))
8 changes: 8 additions & 0 deletions tests/pos/i7888.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
def usingSeq[B](f: [A] => Seq[A] => B): B = {
f(Nil)
}
def crash() = {
usingSeq { [A] => (a: Seq[A]) =>
a
}
}

0 comments on commit 9ecacb1

Please sign in to comment.