From c2c42ece5f022aed9d1bfa7e51de7717d8c3b1f7 Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Tue, 29 Dec 2020 15:12:22 +0200 Subject: [PATCH] Correct bounds for higher-kinded GADT skolems --- .../tools/nsc/typechecker/PatternTypers.scala | 12 +++---- .../scala/reflect/internal/tpe/TypeMaps.scala | 16 ++++----- test/files/pos/t12295.scala | 33 +++++++++++++++++++ 3 files changed, 47 insertions(+), 14 deletions(-) create mode 100644 test/files/pos/t12295.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala index 192483b4ce3c..74bfd0491a14 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala @@ -195,16 +195,16 @@ trait PatternTypers { def skolems = try skolemBuffer.toList finally skolemBuffer.clear() def apply(tp: Type): Type = mapOver(tp) match { - case tp @ TypeRef(NoPrefix, tpSym, Nil) if eligible(tpSym) => - val bounds = ( - if (variance.isInvariant) tpSym.tpeHK.bounds - else if (variance.isPositive) TypeBounds.upper(tpSym.tpeHK) - else TypeBounds.lower(tpSym.tpeHK) + case TypeRef(NoPrefix, tpSym, Nil) if eligible(tpSym) => + val bounds = genPolyType(tpSym.typeParams, + if (variance.isInvariant) tpSym.tpe.bounds + else if (variance.isPositive) TypeBounds.upper(tpSym.tpe) + else TypeBounds.lower(tpSym.tpe) ) // origin must be the type param so we can deskolemize val skolem = context.owner.newGADTSkolem(freshTypeName("?" + tpSym.name), tpSym, bounds) skolemBuffer += skolem - logResult(s"Created gadt skolem $skolem: ${skolem.tpe_*} to stand in for $tpSym")(skolem.tpe_*) + logResult(s"Created gadt skolem $skolem: ${skolem.tpeHK} to stand in for $tpSym")(skolem.tpeHK) case tp1 => tp1 } } diff --git a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala index 5604e7d88e86..2541278dfc12 100644 --- a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala +++ b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala @@ -345,18 +345,18 @@ private[internal] trait TypeMaps { val tp1 = mapOver(tp) if (variance.isInvariant) tp1 else tp1 match { - case TypeRef(pre, sym, args) if tparams.contains(sym) && occurCount(sym) == 1 => - val repl = if (variance.isPositive) dropSingletonType(tp1.upperBound) else tp1.lowerBound + case TypeRef(NoPrefix, sym, Nil) if tparams.contains(sym) && occurCount(sym) == 1 => def msg = { val word = if (variance.isPositive) "upper" else "lower" s"Widened lone occurrence of $tp1 inside existential to $word bound" } - if (!repl.typeSymbol.isBottomClass && ! anyContains.collect(repl)) - debuglogResult(msg)(repl) - else - tp1 - case _ => - tp1 + + val repl = if (variance.isPositive) dropSingletonType(tp1.upperBound) else tp1.lowerBound + val replHK = genPolyType(sym.typeParams, repl) + if (replHK.typeSymbol.isBottomClass || anyContains.collect(replHK)) tp1 + else debuglogResult(msg)(replHK) + case other => + other } } override def mapOver(tp: Type): Type = tp match { diff --git a/test/files/pos/t12295.scala b/test/files/pos/t12295.scala new file mode 100644 index 000000000000..24150cb97103 --- /dev/null +++ b/test/files/pos/t12295.scala @@ -0,0 +1,33 @@ +object Test { + sealed trait Foo[+A] // sealed or not doesn't matter + case class ImplA[A](a: A) extends Foo[A] + case class ImplAny[A](a: Any) extends Foo[A] + + trait Bar[+G[_]] // must be covariant + + def err[F[_]](): Unit = { + val x: Foo[Foo[Bar[F]]] = ??? + + x match { + case ImplAny(ImplAny(_)) => ??? + case ImplAny(ImplA(_)) => ??? + case ImplA(_) => ??? + case ImplAny(_) => ??? + case _ => ??? + } + + x match { + case ImplA(ImplA(_)) => ??? + case ImplA(ImplAny(_)) => ??? + case ImplA(y) => y.toString + case ImplA(y) => y match { + case ImplA(_) => ??? + case _ => ??? + } + case ImplA(y) => y + case _ => ??? + } + + () + } +}