diff options
author | Martin Odersky <odersky@gmail.com> | 2016-07-07 18:24:44 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-07-11 13:35:07 +0200 |
commit | 4693a78edf4bf52b9060a99ca48785d077e5599b (patch) | |
tree | 76885978c6f293ed92b47c21593ef2f22d8e40a2 /src/dotty/tools/dotc/core | |
parent | fd62c7b6dc6882f658ba2d614cb95a7141842929 (diff) | |
download | dotty-4693a78edf4bf52b9060a99ca48785d077e5599b.tar.gz dotty-4693a78edf4bf52b9060a99ca48785d077e5599b.tar.bz2 dotty-4693a78edf4bf52b9060a99ca48785d077e5599b.zip |
Less eager removal of type parameters from constraint
Previously, a unified or otherwise instantiated type parameter
would be removed from the constraint, i.e. if it was the
last parameter of its polytype to be instantiated, the polytype
would be dropped. This is a potential problem since it means
that the alias `param = instance` is forgetten whereas we might
still need it in the same subtype test sequence.
The solution is to wait with cleaning up polytypes until
all associated type variables are fully instantiated.
This change uncovered another bug, where we failed
to follow an existing instantiation when adding to
a constraint. This manifested itself in deep subtype
errors for run/colltest1 and some others.
Diffstat (limited to 'src/dotty/tools/dotc/core')
-rw-r--r-- | src/dotty/tools/dotc/core/Constraint.scala | 9 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/ConstraintHandling.scala | 15 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/OrderingConstraint.scala | 26 |
3 files changed, 26 insertions, 24 deletions
diff --git a/src/dotty/tools/dotc/core/Constraint.scala b/src/dotty/tools/dotc/core/Constraint.scala index 38f714131..e480d1bfe 100644 --- a/src/dotty/tools/dotc/core/Constraint.scala +++ b/src/dotty/tools/dotc/core/Constraint.scala @@ -117,12 +117,11 @@ abstract class Constraint extends Showable { */ def narrowBound(param: PolyParam, bound: Type, isUpper: Boolean)(implicit ctx: Context): This - /** Is entry associated with `pt` removable? - * @param removedParam The index of a parameter which is still present in the - * entry array, but is going to be removed at the same step, - * or -1 if no such parameter exists. + /** Is entry associated with `pt` removable? This is the case if + * all type parameters of the entry are associated with type variables + * which have its `inst` fields set. */ - def isRemovable(pt: GenericType, removedParam: Int = -1): Boolean + def isRemovable(pt: GenericType): Boolean /** A new constraint with all entries coming from `pt` removed. */ def remove(pt: GenericType)(implicit ctx: Context): This diff --git a/src/dotty/tools/dotc/core/ConstraintHandling.scala b/src/dotty/tools/dotc/core/ConstraintHandling.scala index ace441566..dfce9317b 100644 --- a/src/dotty/tools/dotc/core/ConstraintHandling.scala +++ b/src/dotty/tools/dotc/core/ConstraintHandling.scala @@ -164,6 +164,7 @@ trait ConstraintHandling { } } } + assert(constraint.contains(param)) val bound = if (fromBelow) constraint.fullLowerBound(param) else constraint.fullUpperBound(param) val inst = avoidParam(bound) typr.println(s"approx ${param.show}, from below = $fromBelow, bound = ${bound.show}, inst = ${inst.show}") @@ -282,10 +283,16 @@ trait ConstraintHandling { else NoType case bound: TypeVar if constraint contains bound.origin => prune(bound.underlying) - case bound: PolyParam if constraint contains bound => - if (!addParamBound(bound)) NoType - else if (fromBelow) defn.NothingType - else defn.AnyType + case bound: PolyParam => + constraint.entry(bound) match { + case NoType => bound + case _: TypeBounds => + if (!addParamBound(bound)) NoType + else if (fromBelow) defn.NothingType + else defn.AnyType + case inst => + prune(inst) + } case _ => bound } diff --git a/src/dotty/tools/dotc/core/OrderingConstraint.scala b/src/dotty/tools/dotc/core/OrderingConstraint.scala index 1e284c341..b0170b67c 100644 --- a/src/dotty/tools/dotc/core/OrderingConstraint.scala +++ b/src/dotty/tools/dotc/core/OrderingConstraint.scala @@ -11,6 +11,7 @@ import config.Config import config.Printers._ import collection.immutable.BitSet import reflect.ClassTag +import annotation.tailrec object OrderingConstraint { @@ -151,7 +152,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, def contains(param: PolyParam): Boolean = { val entries = boundsMap(param.binder) - entries != null && entries(param.paramNum).isInstanceOf[TypeBounds] + entries != null && isBounds(entries(param.paramNum)) } def contains(tvar: TypeVar): Boolean = { @@ -428,7 +429,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, } var current = - if (isRemovable(poly, idx)) remove(poly) else updateEntry(param, replacement) + if (isRemovable(poly)) remove(poly) else updateEntry(param, replacement) current.foreachParam {(p, i) => current = boundsLens.map(this, current, p, i, replaceParam(_, p, i)) current = lowerLens.map(this, current, p, i, removeParam) @@ -449,20 +450,15 @@ class OrderingConstraint(private val boundsMap: ParamBounds, newConstraint(boundsMap.remove(pt), removeFromOrdering(lowerMap), removeFromOrdering(upperMap)) } - def isRemovable(pt: GenericType, removedParam: Int = -1): Boolean = { + def isRemovable(pt: GenericType): Boolean = { val entries = boundsMap(pt) - var noneLeft = true - var i = paramCount(entries) - while (noneLeft && i > 0) { - i -= 1 - if (i != removedParam && isBounds(entries(i))) noneLeft = false - else typeVar(entries, i) match { - case tv: TypeVar => - if (!tv.inst.exists) noneLeft = false // need to keep line around to compute instType - case _ => + @tailrec def allRemovable(last: Int): Boolean = + if (last < 0) true + else typeVar(entries, last) match { + case tv: TypeVar => tv.inst.exists && allRemovable(last - 1) + case _ => false } - } - noneLeft + allRemovable(paramCount(entries) - 1) } // ---------- Exploration -------------------------------------------------------- @@ -473,7 +469,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, for { (poly, entries) <- boundsMap.toList n <- 0 until paramCount(entries) - if isBounds(entries(n)) + if entries(n).exists } yield PolyParam(poly, n) def forallParams(p: PolyParam => Boolean): Boolean = { |