diff options
author | Martin Odersky <odersky@gmail.com> | 2014-01-01 18:06:30 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-01-01 18:06:30 +0100 |
commit | 3a0e9fbb0018e15c17aea659569202c315ad59f1 (patch) | |
tree | 4942c82ba431cf3bbafa56cbf89ddcf305fee21d /src/dotty/tools/dotc/core/TypeComparer.scala | |
parent | a5611f867c2b9e493d5f0497ddfb813b5daf347d (diff) | |
download | dotty-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.scala | 21 |
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) } |