aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/TypeComparer.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-01-01 18:06:30 +0100
committerMartin Odersky <odersky@gmail.com>2014-01-01 18:06:30 +0100
commit3a0e9fbb0018e15c17aea659569202c315ad59f1 (patch)
tree4942c82ba431cf3bbafa56cbf89ddcf305fee21d /src/dotty/tools/dotc/core/TypeComparer.scala
parenta5611f867c2b9e493d5f0497ddfb813b5daf347d (diff)
downloaddotty-3a0e9fbb0018e15c17aea659569202c315ad59f1.tar.gz
dotty-3a0e9fbb0018e15c17aea659569202c315ad59f1.tar.bz2
dotty-3a0e9fbb0018e15c17aea659569202c315ad59f1.zip
Constraints need to be ignored when forming lubs and glbs of constrained oarameter bounds.
Otherwise we would get into situations like the following (experienced in typers.Arrays): Constraint: B >: String T >: B Add B >: T to this constraint. You get: B >: String | T, but because T >: B >: String, the rhs reduces to B >: T Simplified this gives B = T and the String lower bound has vanished!
Diffstat (limited to 'src/dotty/tools/dotc/core/TypeComparer.scala')
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala21
1 files changed, 18 insertions, 3 deletions
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index 5b945ecb8..cc48f0308 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -24,6 +24,12 @@ class TypeComparer(initctx: Context) extends DotClass {
/** If the constraint is frozen we cannot add new bounds to the constraint. */
protected var frozenConstraint = false
+ /** If the constraint is ignored, subtype checks only take into account
+ * declared bounds of PolyParams. Used when forming unions and intersectons
+ * of constraint bounds
+ */
+ protected var ignoreConstraint = false
+
private var myAnyClass: ClassSymbol = null
private var myNothingClass: ClassSymbol = null
private var myNullClass: ClassSymbol = null
@@ -49,9 +55,14 @@ class TypeComparer(initctx: Context) extends DotClass {
private def addConstraint1(param: PolyParam, bound: Type, fromBelow: Boolean): Boolean = {
val oldBounds = constraint.bounds(param)
assert(!bound.isInstanceOf[TypeVar])
+ val saved = ignoreConstraint
+ ignoreConstraint = true
val newBounds =
- if (fromBelow) oldBounds.derivedTypeBounds(oldBounds.lo | bound, oldBounds.hi)
- else oldBounds.derivedTypeBounds(oldBounds.lo, oldBounds.hi & bound)
+ try
+ if (fromBelow) oldBounds.derivedTypeBounds(oldBounds.lo | bound, oldBounds.hi)
+ else oldBounds.derivedTypeBounds(oldBounds.lo, oldBounds.hi & bound)
+ finally ignoreConstraint = saved
+ // val res = // !!!DEBUG
(param == bound) ||
(oldBounds eq newBounds) || {
val saved = constraint
@@ -59,6 +70,10 @@ class TypeComparer(initctx: Context) extends DotClass {
isSubType(newBounds.lo, newBounds.hi) ||
{ constraint = saved; false } // don't leave the constraint in unsatisfiable state
}
+ //println(s"add constraint $param ${if (fromBelow) ">:" else "<:"} $bound = $res")
+ //if (res)
+ // println(constraint.show)
+ //res
}
/** If current constraint set is not frozen, add the constraint
@@ -405,7 +420,7 @@ class TypeComparer(initctx: Context) extends DotClass {
/** The current bounds of type parameter `param` */
def bounds(param: PolyParam): TypeBounds = constraint at param match {
- case bounds: TypeBounds => bounds
+ case bounds: TypeBounds if !ignoreConstraint => bounds
case _ => param.binder.paramBounds(param.paramNum)
}