Skip to content

Commit c49ae36

Browse files
authored
Merge pull request #7707 from dotty-staging/fix-#7648
Fix #7648: Heal variances when comparing eta-expansions
2 parents 63ba1a3 + 1552e70 commit c49ae36

File tree

3 files changed

+28
-5
lines changed

3 files changed

+28
-5
lines changed

compiler/src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -579,10 +579,15 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
579579
val saved = comparedTypeLambdas
580580
comparedTypeLambdas += tp1
581581
comparedTypeLambdas += tp2
582-
try
583-
variancesConform(tp1.typeParams, tp2.typeParams) &&
584-
boundsOK &&
585-
isSubType(tp1.resType, tp2.resType.subst(tp2, tp1))
582+
val variancesOK =
583+
variancesConform(tp1.typeParams, tp2.typeParams)
584+
|| { // if tp1 is of the form [X] =>> C[X] where `C` is co- or contra-variant
585+
// assume the variance of `C` for `tp1` instead. Fixes #7648.
586+
tp1 match
587+
case EtaExpansion(tycon1) => variancesConform(tycon1.typeParams, tp2.typeParams)
588+
case _ => false
589+
}
590+
try variancesOK && boundsOK && isSubType(tp1.resType, tp2.resType.subst(tp2, tp1))
586591
finally comparedTypeLambdas = saved
587592
case _ =>
588593
val tparams1 = tp1.typeParams

tests/neg/tcpoly_typealias.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ trait BOk4 extends A3 {
3434
// does type alias signature (not considering RHS) correspond to abstract type member in super class
3535
// does RHS correspond to the type alias sig
3636
trait BInv extends A{
37-
type m[x] = FooCov[x] // error: invariant x in alias def
37+
type m[x] = FooCov[x] // was an error: invariant x in alias def, now ok, since `FooCov` is covariant
3838
}
3939

4040
trait BCon extends A{

tests/pos/i7648.scala

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package i7648
2+
3+
class IO[+A]
4+
5+
trait Functor[F[_]]
6+
trait Monad[F[_]] extends Functor[F]
7+
8+
class Stream[+F[_], +A] {
9+
def take[F1[x] >: F[x]](n: Int)(implicit f: Functor[F1]): Stream[F1, A] = {
10+
this
11+
}
12+
}
13+
14+
object Test with
15+
16+
implicit val ioMonad: Monad[IO] = null
17+
18+
val x = new Stream[IO, Int].take[IO](10)

0 commit comments

Comments
 (0)