From 68d58a651ee5a7853e58d40fa1decadd10df110c Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 19 Jan 2015 12:17:24 +0100 Subject: 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. --- src/dotty/tools/dotc/core/ConstraintHandling.scala | 24 +++++-------- src/dotty/tools/dotc/core/TypeComparer.scala | 40 ++++++++-------------- 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 -- cgit v1.2.3