From c73c47aabc7130098fc1712a7c7732f2d5392718 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sun, 22 Jan 2023 18:21:23 +0000 Subject: [PATCH] Fix upper bound constraints, that are higher-kinded When recording an upper bound, when it's a some higher-kinded type variable applied to some type arguments, TypeComparer was re-applying the type arguments to the type parameter (the type variable's origin). Meaning that the instantiation of the type variable won't reflect in the upper bound. See the error message: `F$1[Int]` correctly appears as the lower bound, but `F$1[Int]` isn't the upper bound, `F[Int]` is, which is the original type parameter, in `Foo.Bar.apply[F](..)`. -- [E007] Type Mismatch Error: i12478.scala:8:13 ------------------------------- 8 | Foo.Bar(fu1) | ^^^^^^^^^^^^ |Found: Foo.Bar[F$1] |Required: Foo[T1] | |where: F$1 is a type in method id1 with bounds <: [_] =>> Any | T1 is a type in method id1 with bounds >: F$1[Int] and <: F[Int] | | longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: i12478.scala:18:13 ------------------------------ 18 | Foo.Bar(fu3) | ^^^^^^^^^^^^ |Found: Foo.Bar[F$2] |Required: Foo[T3] | |where: F$2 is a type in method id3 with bounds <: [_] =>> Any | T3 is a type in method id3 with bounds >: F$2[Int] and <: F[Int] | | longer explanation available when compiling with `-explain` --- .../dotty/tools/dotc/core/TypeComparer.scala | 7 +++++-- tests/pos/i12478.scala | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 tests/pos/i12478.scala diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index a0eb5139eb07..cf2507aa1724 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -1338,8 +1338,11 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling } } || tryLiftedToThis2 - case _: TypeVar => - recur(tp1, tp2.superType) + case tv: TypeVar => + if tv.isInstantiated then + recur(tp1, tp2.superType) + else + compareAppliedType2(tp2, tv.origin, args2) case tycon2: AnnotatedType if !tycon2.isRefining => recur(tp1, tp2.superType) case tycon2: AppliedType => diff --git a/tests/pos/i12478.scala b/tests/pos/i12478.scala new file mode 100644 index 000000000000..d1e247ae4e68 --- /dev/null +++ b/tests/pos/i12478.scala @@ -0,0 +1,19 @@ +sealed trait Foo[T] + +object Foo: + case class Bar[F[_]](fu: List[F[Unit]]) extends Foo[F[Unit]] + +class Test: + def id1[T1](foo1: Foo[T1]): Foo[T1] = foo1 match + case Foo.Bar(fu) => + Foo.Bar(fu) + + def id2[T2](foo2: Foo[T2]): Foo[T2] = foo2 match + case bar2 @ (_: Foo.Bar[f]) => + val fu2 = bar2.fu + Foo.Bar(fu2) + + def id3[T3](foo3: Foo[T3]): Foo[T3] = foo3 match + case bar3 @ Foo.Bar(_) => + val fu3 = bar3.fu + Foo.Bar(fu3)