aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-01-24 08:58:51 +0100
committerMartin Odersky <odersky@gmail.com>2014-01-26 18:52:33 +0100
commitf01071323516e699a169d89e5ac848215b6488c2 (patch)
treee1748ff03980ebe605171ad9d5601b24f31ff813 /src/dotty/tools
parentea241b57322ccb818c6a95effc28e0db6d4f38b2 (diff)
downloaddotty-f01071323516e699a169d89e5ac848215b6488c2.tar.gz
dotty-f01071323516e699a169d89e5ac848215b6488c2.tar.bz2
dotty-f01071323516e699a169d89e5ac848215b6488c2.zip
Fixing two bugs in subtype checking that cancelled each other out.
1. The occursInCheck hat its logic crossed, which led to some cycles in constraints not being detected. 2. The logic around addConstraint skipped some necessary comparisons when frozenConstraint was set. Fixing the addConstraint logic created new subtype cases which made constraints cyclic without that fact being detected.
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala15
-rw-r--r--src/dotty/tools/dotc/core/Types.scala2
2 files changed, 8 insertions, 9 deletions
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index c978affb6..221b20e51 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -104,10 +104,8 @@ class TypeComparer(initctx: Context) extends DotClass {
* @return Whether the augmented constraint is still satisfiable.
*/
def addConstraint(param: PolyParam, bound0: Type, fromBelow: Boolean): Boolean = {
+ assert(!frozenConstraint)
val bound = bound0.dealias.stripTypeVar
- param == bound || // ###
- !frozenConstraint && { // ###
-
constr.println(s"adding ${param.show} ${if (fromBelow) ">:>" else "<:<"} ${bound.show} (${bound.getClass}) to ${constraint.show}")
val res = bound match {
case bound: PolyParam if constraint contains bound =>
@@ -133,7 +131,6 @@ class TypeComparer(initctx: Context) extends DotClass {
}
constr.println(s"added ${param.show} ${if (fromBelow) ">:>" else "<:<"} ${bound.show} = ${constraint.show}")
res
- } // ###
}
def isConstrained(param: PolyParam): Boolean =
@@ -174,7 +171,7 @@ class TypeComparer(initctx: Context) extends DotClass {
def isNonBottomSubType(tp1: Type, tp2: Type): Boolean =
!(tp2 isRef NothingClass) && isSubType(tp1, tp2)
- def isSubType(tp1: Type, tp2: Type): Boolean =
+ def isSubType(tp1: Type, tp2: Type): Boolean = ctx.traceIndented(s"isSubType ${tp1.show} <:< ${tp2.show}", subtyping) {
if (tp1 == NoType || tp2 == NoType) false
else if (tp1 eq tp2) true
else {
@@ -213,11 +210,13 @@ class TypeComparer(initctx: Context) extends DotClass {
throw ex
}
}
+ }
def monitoredIsSubType(tp1: Type, tp2: Type) = {
if (pendingSubTypes == null) {
pendingSubTypes = new mutable.HashSet[(Type, Type)]
ctx.log(s"!!! deep subtype recursion involving ${tp1.show} <:< ${tp2.show}, constraint = ${ctx.typerState.constraint.show}")
+ assert(!Config.flagDeepRecursions)
if (Config.traceDeepSubTypes && !this.isInstanceOf[ExplainingTypeComparer])
ctx.log(TypeComparer.explained(implicit ctx => ctx.typeComparer.isSubType(tp1, tp2)))
}
@@ -533,7 +532,7 @@ class TypeComparer(initctx: Context) extends DotClass {
def comparePolyParam = {
tp2 == tp1 ||
isSubTypeWhenFrozen(tp1, bounds(tp2).lo) || {
- if (constraint contains tp2) addConstraint(tp2, tp1.widen, fromBelow = true)
+ if (isConstrained(tp2)) addConstraint(tp2, tp1.widen, fromBelow = true)
else (ctx.mode is Mode.TypevarsMissContext) || secondTry(tp1, tp2)
}
}
@@ -581,7 +580,7 @@ class TypeComparer(initctx: Context) extends DotClass {
(tp2 isRef defn.NothingClass) &&
ctx.typerState.isGlobalCommittable)
ctx.log(s"!!! instantiating to Nothing: $tp1")
- if (constraint contains tp1) addConstraint(tp1, tp2, fromBelow = false)
+ if (isConstrained(tp1)) addConstraint(tp1, tp2, fromBelow = false)
else (ctx.mode is Mode.TypevarsMissContext) || thirdTry(tp1, tp2)
}
}
@@ -766,7 +765,7 @@ class TypeComparer(initctx: Context) extends DotClass {
}
else isSubType(tp1, tp2)
- /** A type has been covered previously in subtype check if it
+ /** A type has been covered previously in subtype checking if it
* is some combination of TypeRefs that point to classes, where the
* combiners are RefinedTypes, AndTypes or AnnotatedTypes.
*/
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 622672515..bfe4ae5be 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -1701,7 +1701,7 @@ object Types {
case bound: AndOrType =>
def occ1 = occursIn(bound.tp1, fromBelow)
def occ2 = occursIn(bound.tp2, fromBelow)
- if (fromBelow == bound.isAnd) occ1 || occ2 else occ1 & occ2
+ if (fromBelow == bound.isAnd) occ1 & occ2 else occ1 || occ2
case _ => false
}