aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/core/Skolemization.scala23
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala7
2 files changed, 21 insertions, 9 deletions
diff --git a/src/dotty/tools/dotc/core/Skolemization.scala b/src/dotty/tools/dotc/core/Skolemization.scala
index fb47cb62a..af7530458 100644
--- a/src/dotty/tools/dotc/core/Skolemization.scala
+++ b/src/dotty/tools/dotc/core/Skolemization.scala
@@ -18,26 +18,33 @@ trait Skolemization {
implicit val ctx: Context
- protected var skolemsOutstanding = false
+ private[core] var skolemsState = Skolemization.SkolemsDisallowed
- def ensureStableSingleton(tp: Type): SingletonType = tp.stripTypeVar match {
+ final def ensureStableSingleton(tp: Type): SingletonType = tp.stripTypeVar match {
case tp: SingletonType if tp.isStable =>
tp
case tp: ValueType =>
- skolemsOutstanding = true
+ assert(skolemsState != Skolemization.SkolemsDisallowed)
+ skolemsState = Skolemization.SkolemsEncountered
SkolemType(tp)
case tp: TypeProxy =>
ensureStableSingleton(tp.underlying)
}
- /** Approximate a type `tp` with a type that does not contain skolem types.
+ /** If skolems were encountered, approximate a type `tp` with a type that
+ * does not contain skolem types.
* @param toSuper if true, return the smallest supertype of `tp` with this property
* else return the largest subtype.
*/
- final def deSkolemize(tp: Type, toSuper: Boolean): Type =
- if (skolemsOutstanding) deSkolemize(tp, if (toSuper) 1 else -1, Set())
+ final def deSkolemizeIfSkolemsSeen(tp: Type, toSuper: Boolean): Type =
+ if (skolemsState == Skolemization.SkolemsEncountered)
+ deSkolemize(tp, if (toSuper) 1 else -1, Set())
else tp
+ /** Approximate a type `tp` with a type that does not contain skolem types.
+ */
+ final def deSkolemize(tp: Type): Type = deSkolemize(tp, 1, Set())
+
private def deSkolemize(tp: Type, variance: Int, seen: Set[SkolemType]): Type =
ctx.traceIndented(s"deskolemize $tp, variance = $variance, seen = $seen = ") {
def approx(lo: Type = defn.NothingType, hi: Type = defn.AnyType, newSeen: Set[SkolemType] = seen) =
@@ -124,3 +131,7 @@ trait Skolemization {
}
}
}
+
+object Skolemization extends Enumeration {
+ val SkolemsDisallowed, SkolemsAllowed, SkolemsEncountered = Value
+}
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index 9559666a4..692f05d5a 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -531,7 +531,8 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
* rebase both itself and the member info of `tp` on a freshly created skolem type.
*/
protected def hasMatchingMember(name: Name, tp1: Type, tp2: RefinedType): Boolean = {
- val saved = skolemsOutstanding
+ val saved = skolemsState
+ if (skolemsState == Skolemization.SkolemsDisallowed) skolemsState = Skolemization.SkolemsAllowed
try {
val rebindNeeded = tp2.refinementRefersToThis
val base = if (rebindNeeded) ensureStableSingleton(tp1) else tp1
@@ -555,7 +556,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
}
}
}
- finally skolemsOutstanding = saved
+ finally skolemsState = saved
}
/** Skip refinements in `tp2` which match corresponding refinements in `tp1`.
@@ -640,7 +641,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
private def narrowGADTBounds(tr: NamedType, bound: Type, isUpper: Boolean): Boolean =
ctx.mode.is(Mode.GADTflexible) && {
val tparam = tr.symbol
- val bound1 = deSkolemize(bound, toSuper = !isUpper)
+ val bound1 = deSkolemizeIfSkolemsSeen(bound, toSuper = !isUpper)
typr.println(s"narrow gadt bound of $tparam: ${tparam.info} from ${if (isUpper) "above" else "below"} to $bound1 ${bound1.isRef(tparam)}")
!bound1.isRef(tparam) && {
val oldBounds = ctx.gadt.bounds(tparam)