diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 4e911eed5bf4..7dec61044aa9 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -413,6 +413,9 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { // of an `AndType` can lead to a cascade of subtyping checks // This twist is needed to make collection/generic/ParFactory.scala compile fourthTry(tp1, tp2) || compareRefinedSlow + case tp1: HKTypeLambda => + // HKTypeLambdas do not have members. + fourthTry(tp1, tp2) case _ => compareRefinedSlow || fourthTry(tp1, tp2) } diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 3dd56aa1cebf..ca7f63ee12a3 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -132,7 +132,10 @@ object Types { case _ => this1.symbol eq sym } case this1: RefinedOrRecType => this1.parent.isRef(sym) - case this1: HKApply => this1.superType.isRef(sym) + case this1: HKApply => + val this2 = this1.dealias + if (this2 ne this1) this2.isRef(sym) + else this1.underlying.isRef(sym) case _ => false } diff --git a/tests/neg/i2971.scala b/tests/neg/i2971.scala new file mode 100644 index 000000000000..6d4ca082773e --- /dev/null +++ b/tests/neg/i2971.scala @@ -0,0 +1,20 @@ +case class Foo[+X[_]](will: X[Int]) { + def foo[Y[_]](right: Foo[Y]) = Foo.doFoo(this, right) +} + +class A[X] { def crash = true } +class B[X] + +object Foo { + def doFoo[X[_]](left: Foo[X], right: Foo[X]): Foo[X] = right + + def main(args: Array[String]): Unit = { + val fooA = Foo(new A[Int]) + val fooB = Foo(new B[Int]) + // The type for this is inferred correctly to Foo[A|B] + val fine = doFoo(fooA, fooB) + // This throws a ClassCastException because fooB isn't a Foo[A] + val oops: Foo[A] = fooA.foo(fooB) // error: found: Foo[B], required: Foo[A] + println(oops.will.crash) + } +}