Skip to content

Commit

Permalink
Correct bounds for higher-kinded GADT skolems
Browse files Browse the repository at this point in the history
  • Loading branch information
joroKr21 committed Dec 29, 2020
1 parent 1851c5d commit c2c42ec
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 14 deletions.
12 changes: 6 additions & 6 deletions src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
Expand Up @@ -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
}
}
Expand Down
16 changes: 8 additions & 8 deletions src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
Expand Up @@ -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 {
Expand Down
33 changes: 33 additions & 0 deletions 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 _ => ???
}

()
}
}

0 comments on commit c2c42ec

Please sign in to comment.