aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-01-19 12:17:24 +0100
committerMartin Odersky <odersky@gmail.com>2015-01-19 12:30:45 +0100
commit68d58a651ee5a7853e58d40fa1decadd10df110c (patch)
tree2c0ea145a984731af5f4b84d0cfa7418a3b3d414
parent01f1a26bbfa6763eba960ac71f9d71cebed478df (diff)
downloaddotty-68d58a651ee5a7853e58d40fa1decadd10df110c.tar.gz
dotty-68d58a651ee5a7853e58d40fa1decadd10df110c.tar.bz2
dotty-68d58a651ee5a7853e58d40fa1decadd10df110c.zip
Move PolyParam test later in isSubType and simplify addConstraint
Motivation: Would like to profit from normalizations done before, so that we do not have to redo them in addConstraint. Also: eliminate solvedConstraint; it is no longer needed and was always false.
-rw-r--r--src/dotty/tools/dotc/core/ConstraintHandling.scala24
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala40
2 files changed, 24 insertions, 40 deletions
diff --git a/src/dotty/tools/dotc/core/ConstraintHandling.scala b/src/dotty/tools/dotc/core/ConstraintHandling.scala
index ff7ffdfb1..e79dc28b9 100644
--- a/src/dotty/tools/dotc/core/ConstraintHandling.scala
+++ b/src/dotty/tools/dotc/core/ConstraintHandling.scala
@@ -197,8 +197,6 @@ trait ConstraintHandling {
finally constraint = saved
}
- protected def solvedConstraint = false
-
/** The current bounds of type parameter `param` */
final def bounds(param: PolyParam): TypeBounds = constraint.entry(param) match {
case bounds: TypeBounds => bounds
@@ -228,28 +226,24 @@ trait ConstraintHandling {
isSubTypeWhenFrozen(tp, bounds(param).lo)
final def canConstrain(param: PolyParam): Boolean =
- !frozenConstraint && !solvedConstraint && (constraint contains param)
+ !frozenConstraint && (constraint contains param)
+ /** Add constraint `param <: bond` if `fromBelow` is true, `param >: bound` otherwise.
+ * `bound` is assumed to be in normalized form, as specified in `firstTry` and
+ * `secondTry` of `TypeComparer`. In particular, it should not be an alias type,
+ * lazy ref, typevar, wildcard type, error type. In addition, upper bounds may
+ * not be AndTypes and lower bounds may not be OrTypes.
+ */
protected def addConstraint(param: PolyParam, bound: Type, fromBelow: Boolean): Boolean = {
def description = i"constr $param ${if (fromBelow) ">:" else "<:"} $bound:\n$constraint"
checkPropagated(s"adding $description")(true)
checkPropagated(s"added $description") {
addConstraintInvocations += 1
- try bound.dealias.stripTypeVar match {
+ try bound match {
case bound: PolyParam if constraint contains bound =>
if (fromBelow) addLess(bound, param) else addLess(param, bound)
- case bound: AndOrType if fromBelow != bound.isAnd =>
- addConstraint(param, bound.tp1, fromBelow) && addConstraint(param, bound.tp2, fromBelow)
- case bound: WildcardType =>
- bound.optBounds match {
- case TypeBounds(lo, hi) => addConstraint(param, if (fromBelow) lo else hi, fromBelow)
- case NoType => true
- }
- case bound: ErrorType =>
- true
case _ =>
- if (fromBelow) addLowerBound(param, bound)
- else addUpperBound(param, bound)
+ if (fromBelow) addLowerBound(param, bound) else addUpperBound(param, bound)
}
finally addConstraintInvocations -= 1
}
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index f8e4d3e4b..292c83a6d 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -193,18 +193,6 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
compareNamed
case tp2: ProtoType =>
isMatchedByProto(tp2, tp1)
- case tp2: PolyParam =>
- def comparePolyParam =
- tp2 == tp1 || {
- if (solvedConstraint && (constraint contains tp2)) isSubType(tp1, bounds(tp2).lo)
- else
- (ctx.mode is Mode.TypevarsMissContext) ||
- constraintImpliesSuper(tp2, tp1) || {
- if (canConstrain(tp2)) addConstraint(tp2, tp1.widenExpr, fromBelow = true)
- else secondTry(tp1, tp2)
- }
- }
- comparePolyParam
case tp2: BoundType =>
tp2 == tp1 || secondTry(tp1, tp2)
case tp2: TypeVar =>
@@ -266,15 +254,11 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
true
}
def comparePolyParam =
- tp1 == tp2 || {
- if (solvedConstraint && (constraint contains tp1)) isSubType(bounds(tp1).lo, tp2)
- else
- (ctx.mode is Mode.TypevarsMissContext) ||
- constraintImpliesSub(tp1, tp2) || {
- if (canConstrain(tp1)) addConstraint(tp1, tp2, fromBelow = false) && flagNothingBound
- else thirdTry(tp1, tp2)
- }
- }
+ (ctx.mode is Mode.TypevarsMissContext) ||
+ constraintImpliesSub(tp1, tp2) || {
+ if (canConstrain(tp1)) addConstraint(tp1, tp2, fromBelow = false) && flagNothingBound
+ else thirdTry(tp1, tp2)
+ }
comparePolyParam
case tp1: ThisType =>
tp2 match {
@@ -288,8 +272,6 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
case tp2: SkolemType if tp1 == tp2 => true
case _ => thirdTry(tp1, tp2)
}
- case tp1: BoundType =>
- tp1 == tp2 || thirdTry(tp1, tp2)
case tp1: TypeVar =>
(tp1 eq tp2) || isSubType(tp1.underlying, tp2)
case tp1: WildcardType =>
@@ -335,6 +317,14 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
private def thirdTry(tp1: Type, tp2: Type): Boolean = tp2 match {
case tp2: NamedType =>
thirdTryNamed(tp1, tp2)
+ case tp2: PolyParam =>
+ def comparePolyParam =
+ (ctx.mode is Mode.TypevarsMissContext) ||
+ constraintImpliesSuper(tp2, tp1) || {
+ if (canConstrain(tp2)) addConstraint(tp2, tp1.widenExpr, fromBelow = true)
+ else fourthTry(tp1, tp2)
+ }
+ comparePolyParam
case tp2: RefinedType =>
def compareRefined: Boolean = {
val tp1w = tp1.widen
@@ -599,7 +589,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
/** Defer constraining type variables when compared against prototypes */
def isMatchedByProto(proto: ProtoType, tp: Type) = tp.stripTypeVar match {
- case tp: PolyParam if !solvedConstraint && (constraint contains tp) => true
+ case tp: PolyParam if constraint contains tp => true
case _ => proto.isMatchedBy(tp)
}
@@ -610,7 +600,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
* type variable with (the corresponding type in) `tp2` instead.
*/
private def isCappable(tp: Type): Boolean = tp match {
- case tp: PolyParam => !solvedConstraint && (constraint contains tp)
+ case tp: PolyParam => constraint contains tp
case tp: TypeProxy => isCappable(tp.underlying)
case tp: AndOrType => isCappable(tp.tp1) || isCappable(tp.tp2)
case _ => false