From 7387da3e41e90aa6e9ea29e6218165000e07e454 Mon Sep 17 00:00:00 2001 From: Miles Sabin Date: Sun, 24 Mar 2019 13:08:26 +0000 Subject: [PATCH 1/3] Preserve tvar bounds that represent kinds The kinds of type variables being solved are represented by by their upper bounds. If we loose track of these then kinds will be incorrect on the RHS of inline matches and match types. Without the additional change in TypeComparer this breaks tests/pos/i5574.scala. The added fallback to fourthTry brings the higher kinded case into line with the path that's followed in the simply kinded case and restores the correct behaviour. Unfortunately I'm not able to justify it other than that it emerged from extensive trial and error and comparison with the simply kinded case. I'd also love to understand the use return in TypeComparer. Is it an optimization or does it have some semantic significance? Fixes #6014. --- .../src/dotty/tools/dotc/core/Contexts.scala | 5 +++- .../dotty/tools/dotc/core/TypeComparer.scala | 2 +- compiler/test/dotc/pos-from-tasty.blacklist | 1 + tests/pos/i6014.scala | 25 +++++++++++++++++++ 4 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 tests/pos/i6014.scala diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index b3a9fe523872..1674b3e55d31 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -929,7 +929,10 @@ object Contexts { // - we don't want TyperState instantiating these TypeVars // - we don't want TypeComparer constraining these TypeVars val poly = PolyType(DepParamName.fresh(sym.name.toTypeName) :: Nil)( - pt => TypeBounds.empty :: Nil, + pt => (sym.info match { + case tb @ TypeBounds(lo, hi) if (lo eq defn.NothingType) && hi.isLambdaSub => tb + case _ => TypeBounds.empty + }) :: Nil, pt => defn.AnyType) new TypeVar(poly.paramRefs.head, creatorState = null) } diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 3e7fce488a6a..2c4f575b55de 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -559,7 +559,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] { if (tparams1.nonEmpty) return recur( HKTypeLambda.fromParams(tparams1, tp1.appliedTo(tparams1.map(_.paramRef))), - tp2) + tp2) || fourthTry else tp2 match { case EtaExpansion(tycon2) if tycon2.symbol.isClass => return recur(tp1, tycon2) diff --git a/compiler/test/dotc/pos-from-tasty.blacklist b/compiler/test/dotc/pos-from-tasty.blacklist index 35dd21fcbcbf..2324518331cf 100644 --- a/compiler/test/dotc/pos-from-tasty.blacklist +++ b/compiler/test/dotc/pos-from-tasty.blacklist @@ -27,3 +27,4 @@ t6278-synth-def.scala # Need to print empty tree for implicit match i5938.scala +i6014.scala diff --git a/tests/pos/i6014.scala b/tests/pos/i6014.scala new file mode 100644 index 000000000000..e22018beb4b0 --- /dev/null +++ b/tests/pos/i6014.scala @@ -0,0 +1,25 @@ +import scala.compiletime._ + +object Test1 { + type Foo[F[_]] + type Bar[T] = T match { + case Foo[f] => f[Int] + } + + val li: Bar[Foo[List]] = List(1, 2, 3) +} + +object Test2 { + inline def summon[T] = implicit match { + case t: T => t + } + + class Foo[F[_]] + + inline def bar[T] = inline erasedValue[T] match { + case _: Foo[f] => summon[f[Int]] + } + + implicit val li: List[Int] = List(1, 2, 3) + bar[Foo[List]] +} From bee6ff77ef4a554a55bda7666606d985ad4f63c2 Mon Sep 17 00:00:00 2001 From: Miles Sabin Date: Mon, 25 Mar 2019 11:04:27 +0000 Subject: [PATCH 2/3] Relaxed constraint on lower bound and added tests --- .../src/dotty/tools/dotc/core/Contexts.scala | 2 +- tests/pos/i6014.scala | 34 ++++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 1674b3e55d31..9ac722cf0164 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -930,7 +930,7 @@ object Contexts { // - we don't want TypeComparer constraining these TypeVars val poly = PolyType(DepParamName.fresh(sym.name.toTypeName) :: Nil)( pt => (sym.info match { - case tb @ TypeBounds(lo, hi) if (lo eq defn.NothingType) && hi.isLambdaSub => tb + case tb @ TypeBounds(_, hi) if hi.isLambdaSub => tb case _ => TypeBounds.empty }) :: Nil, pt => defn.AnyType) diff --git a/tests/pos/i6014.scala b/tests/pos/i6014.scala index e22018beb4b0..721c638051f0 100644 --- a/tests/pos/i6014.scala +++ b/tests/pos/i6014.scala @@ -21,5 +21,37 @@ object Test2 { } implicit val li: List[Int] = List(1, 2, 3) - bar[Foo[List]] + val lii = bar[Foo[List]] +} + +object Test3 { + inline def summon[T] = implicit match { + case t: T => t + } + + type K1Top = [t] => Any + + class Foo[F <: K1Top] + + inline def bar[T] = inline erasedValue[T] match { + case _: Foo[f] => summon[f[Int]] + } + + implicit val li: List[Int] = List(1, 2, 3) + val lii = bar[Foo[List]] +} + +object Test4 { + inline def summon[T] = implicit match { + case t: T => t + } + + class Foo[F[t] >: List[t]] + + inline def bar[T] = inline erasedValue[T] match { + case _: Foo[f] => summon[f[Int]] + } + + implicit val li: List[Int] = List(1, 2, 3) + val lii = bar[Foo[List]] } From b9165fefed1d21897b57feb13c108218c38e1709 Mon Sep 17 00:00:00 2001 From: Miles Sabin Date: Mon, 25 Mar 2019 13:55:04 +0000 Subject: [PATCH 3/3] Renamed test --- compiler/test/dotc/pos-from-tasty.blacklist | 2 +- tests/pos/{i6014.scala => i6014-gadt.scala} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename tests/pos/{i6014.scala => i6014-gadt.scala} (100%) diff --git a/compiler/test/dotc/pos-from-tasty.blacklist b/compiler/test/dotc/pos-from-tasty.blacklist index 2324518331cf..ab7eb65a765d 100644 --- a/compiler/test/dotc/pos-from-tasty.blacklist +++ b/compiler/test/dotc/pos-from-tasty.blacklist @@ -27,4 +27,4 @@ t6278-synth-def.scala # Need to print empty tree for implicit match i5938.scala -i6014.scala +i6014-gadt.scala diff --git a/tests/pos/i6014.scala b/tests/pos/i6014-gadt.scala similarity index 100% rename from tests/pos/i6014.scala rename to tests/pos/i6014-gadt.scala