aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/Constraint.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-12-31 19:13:17 +0100
committerMartin Odersky <odersky@gmail.com>2013-12-31 19:13:48 +0100
commit2623e52d088b9cdd79255097b658c064437df5e0 (patch)
treec666167fc46edbbecc5cb5e710d587cd2e4a6b57 /src/dotty/tools/dotc/core/Constraint.scala
parent821fa9b9e832adfd68a55e5705dc165096a86a38 (diff)
downloaddotty-2623e52d088b9cdd79255097b658c064437df5e0.tar.gz
dotty-2623e52d088b9cdd79255097b658c064437df5e0.tar.bz2
dotty-2623e52d088b9cdd79255097b658c064437df5e0.zip
Check that constraints are not cyclic, and avoid cycles when replacing parameters.
Diffstat (limited to 'src/dotty/tools/dotc/core/Constraint.scala')
-rw-r--r--src/dotty/tools/dotc/core/Constraint.scala48
1 files changed, 44 insertions, 4 deletions
diff --git a/src/dotty/tools/dotc/core/Constraint.scala b/src/dotty/tools/dotc/core/Constraint.scala
index a1f52cad7..a9fa8f0c6 100644
--- a/src/dotty/tools/dotc/core/Constraint.scala
+++ b/src/dotty/tools/dotc/core/Constraint.scala
@@ -2,11 +2,12 @@ package dotty.tools
package dotc
package core
-import Types._, Contexts._
+import Types._, Contexts._, Symbols._
import util.SimpleMap
import collection.mutable
import printing.{Printer, Showable}
import printing.Texts._
+import config.Config
/** Constraint over undetermined type parameters
* @param myMap a map from PolyType to arrays.
@@ -64,6 +65,7 @@ class Constraint(val myMap: SimpleMap[PolyType, Array[Type]]) extends AnyVal wit
private def updateEntries(pt: PolyType, entries: Array[Type]): Constraint = {
import Constraint._
val res = new Constraint(myMap.updated(pt, entries))
+ if (Config.checkConstraintsNonCyclic) checkNonCyclic(pt, entries)
if (res.myMap.size > maxSize) {
maxSize = res.myMap.size
maxConstraint = res
@@ -71,6 +73,18 @@ class Constraint(val myMap: SimpleMap[PolyType, Array[Type]]) extends AnyVal wit
res
}
+ /** Check that no constrained parameter contains itself as a bound */
+ def checkNonCyclic(pt: PolyType, entries: Array[Type]) =
+ for ((entry, i) <- entries.zipWithIndex) {
+ val param = PolyParam(pt, i)
+ entry match {
+ case TypeBounds(lo, hi) =>
+ assert(lo != param, param)
+ assert(hi != param, param)
+ case _ =>
+ }
+ }
+
/** A new constraint which is derived from this constraint by updating
* the entry for parameter `param` to `tpe`.
* @pre `this contains param`.
@@ -117,7 +131,33 @@ class Constraint(val myMap: SimpleMap[PolyType, Array[Type]]) extends AnyVal wit
* of the parameter elsewhere in the constraint by type `tp`.
*/
def replace(param: PolyParam, tp: Type)(implicit ctx: Context): Constraint = {
- def subst(entries: Array[Type]) = {
+
+ /** Drop parameter `PolyParam(poly, n)` from bounds in type `tp` */
+ def dropParamIn(tp: Type, poly: PolyType, n: Int, fromBelow: Boolean = false): Type = {
+ def drop(tp: Type): Type = tp match {
+ case tp: AndOrType =>
+ val tp1 = drop(tp.tp1)
+ val tp2 = drop(tp.tp2)
+ if (!tp1.exists) tp2
+ else if (!tp2.exists) tp1
+ else tp
+ case PolyParam(`poly`, `n`) => NoType
+ case _ => tp
+ }
+ tp match {
+ case tp: TypeBounds =>
+ tp.derivedTypeBounds(
+ dropParamIn(tp.lo, poly, n, !fromBelow),
+ dropParamIn(tp.hi, poly, n, fromBelow))
+ case _ =>
+ val tp1 = drop(tp)
+ if (tp1.exists || !tp.exists) tp1
+ else if (fromBelow) defn.NothingType
+ else defn.AnyType
+ }
+ }
+
+ def subst(poly: PolyType, entries: Array[Type]) = {
var result = entries
var i = 0
while (i < paramCount(entries)) {
@@ -126,7 +166,7 @@ class Constraint(val myMap: SimpleMap[PolyType, Array[Type]]) extends AnyVal wit
val newBounds = oldBounds.substParam(param, tp)
if (oldBounds ne newBounds) {
if (result eq entries) result = entries.clone
- result(i) = newBounds
+ result(i) = dropParamIn(newBounds, poly, i, fromBelow = false)
}
case _ =>
}
@@ -134,12 +174,12 @@ class Constraint(val myMap: SimpleMap[PolyType, Array[Type]]) extends AnyVal wit
}
result
}
+
val pt = param.binder
val constr1 = if (isRemovable(pt, param.paramNum)) remove(pt) else updated(param, tp)
new Constraint(constr1.myMap mapValues subst)
}
-
/** A new constraint which is derived from this constraint by adding
* entries for all type parameters of `poly`.
*/