aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/config/Config.scala3
-rw-r--r--src/dotty/tools/dotc/core/Constraint.scala3
-rw-r--r--src/dotty/tools/dotc/core/OrderingConstraint.scala30
-rw-r--r--src/dotty/tools/dotc/core/TyperState.scala8
-rw-r--r--src/dotty/tools/dotc/core/Types.scala3
-rw-r--r--tests/pos/t8230a.scala (renamed from tests/pending/pos/t8230a.scala)10
6 files changed, 46 insertions, 11 deletions
diff --git a/src/dotty/tools/dotc/config/Config.scala b/src/dotty/tools/dotc/config/Config.scala
index 782a2f2d3..9e9974bdc 100644
--- a/src/dotty/tools/dotc/config/Config.scala
+++ b/src/dotty/tools/dotc/config/Config.scala
@@ -32,6 +32,9 @@ object Config {
*/
final val checkConstraintsPropagated = false
+ /** Check that constraints of globally committable typer states are closed */
+ final val checkConstraintsClosed = true
+
/** Check that no type appearing as the info of a SymDenotation contains
* skolem types.
*/
diff --git a/src/dotty/tools/dotc/core/Constraint.scala b/src/dotty/tools/dotc/core/Constraint.scala
index 5a758f144..19f93ce47 100644
--- a/src/dotty/tools/dotc/core/Constraint.scala
+++ b/src/dotty/tools/dotc/core/Constraint.scala
@@ -146,4 +146,7 @@ abstract class Constraint extends Showable {
/** Check that no constrained parameter contains itself as a bound */
def checkNonCyclic()(implicit ctx: Context): Unit
+
+ /** Check that constraint only refers to PolyParams bound by itself */
+ def checkClosed()(implicit ctx: Context): Unit
}
diff --git a/src/dotty/tools/dotc/core/OrderingConstraint.scala b/src/dotty/tools/dotc/core/OrderingConstraint.scala
index 21d003451..4c52f58e8 100644
--- a/src/dotty/tools/dotc/core/OrderingConstraint.scala
+++ b/src/dotty/tools/dotc/core/OrderingConstraint.scala
@@ -399,7 +399,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
def removeParam(ps: List[PolyParam]) =
ps.filterNot(p => p.binder.eq(poly) && p.paramNum == idx)
- def replaceParam(tp: Type, atPoly: PolyType, atIdx: Int) = tp match {
+ def replaceParam(tp: Type, atPoly: PolyType, atIdx: Int): Type = tp match {
case bounds @ TypeBounds(lo, hi) =>
def recombine(andor: AndOrType, op: (Type, Boolean) => Type, isUpper: Boolean): Type = {
@@ -424,7 +424,8 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
}
bounds.derivedTypeBounds(replaceIn(lo, isUpper = false), replaceIn(hi, isUpper = true))
- case _ => tp
+ case _ =>
+ tp.substParam(param, replacement)
}
var current =
@@ -438,8 +439,16 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
}
}
- def remove(pt: PolyType)(implicit ctx: Context): This =
- newConstraint(boundsMap.remove(pt), lowerMap.remove(pt), upperMap.remove(pt))
+ def remove(pt: PolyType)(implicit ctx: Context): This = {
+ def removeFromOrdering(po: ParamOrdering) = {
+ def removeFromBoundss(key: PolyType, bndss: Array[List[PolyParam]]): Array[List[PolyParam]] = {
+ val bndss1 = bndss.map(bnds => bnds.filterConserve(_.binder ne pt))
+ if ((0 until bndss.length).forall(i => bndss(i) eq bndss1(i))) bndss else bndss1
+ }
+ po.remove(pt).mapValues(removeFromBoundss)
+ }
+ newConstraint(boundsMap.remove(pt), removeFromOrdering(lowerMap), removeFromOrdering(upperMap))
+ }
def isRemovable(pt: PolyType, removedParam: Int = -1): Boolean = {
val entries = boundsMap(pt)
@@ -491,6 +500,19 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
}
}
+ override def checkClosed()(implicit ctx: Context): Unit = {
+ def isFreePolyParam(tp: Type) = tp match {
+ case PolyParam(binder, _) => !contains(binder)
+ case _ => false
+ }
+ def checkClosedType(tp: Type, where: String) =
+ if (tp != null)
+ assert(!tp.existsPart(isFreePolyParam), i"unclosed constraint: $this refers to $tp in $where")
+ boundsMap.foreachBinding((_, tps) => tps.foreach(checkClosedType(_, "bounds")))
+ lowerMap.foreachBinding((_, paramss) => paramss.foreach(_.foreach(checkClosedType(_, "lower"))))
+ upperMap.foreachBinding((_, paramss) => paramss.foreach(_.foreach(checkClosedType(_, "upper"))))
+ }
+
private var myUninstVars: mutable.ArrayBuffer[TypeVar] = _
/** The uninstantiated typevars of this constraint */
diff --git a/src/dotty/tools/dotc/core/TyperState.scala b/src/dotty/tools/dotc/core/TyperState.scala
index 91cda1dd8..ba7a6a806 100644
--- a/src/dotty/tools/dotc/core/TyperState.scala
+++ b/src/dotty/tools/dotc/core/TyperState.scala
@@ -9,6 +9,7 @@ import util.{SimpleMap, DotClass}
import reporting._
import printing.{Showable, Printer}
import printing.Texts._
+import config.Config
import collection.mutable
class TyperState(r: Reporter) extends DotClass with Showable {
@@ -19,7 +20,7 @@ class TyperState(r: Reporter) extends DotClass with Showable {
/** The current constraint set */
def constraint: Constraint =
new OrderingConstraint(SimpleMap.Empty, SimpleMap.Empty, SimpleMap.Empty)
- def constraint_=(c: Constraint): Unit = {}
+ def constraint_=(c: Constraint)(implicit ctx: Context): Unit = {}
/** The uninstantiated variables */
def uninstVars = constraint.uninstVars
@@ -85,7 +86,10 @@ extends TyperState(r) {
private var myConstraint: Constraint = previous.constraint
override def constraint = myConstraint
- override def constraint_=(c: Constraint) = myConstraint = c
+ override def constraint_=(c: Constraint)(implicit ctx: Context) = {
+ if (Config.checkConstraintsClosed && isGlobalCommittable) c.checkClosed()
+ myConstraint = c
+ }
private var myEphemeral: Boolean = previous.ephemeral
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 026e69539..1270466e9 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -2458,6 +2458,9 @@ object Types {
if (fromBelow && isOrType(inst) && isFullyDefined(inst) && !isOrType(upperBound))
inst = inst.approximateUnion
+ if (ctx.typerState.isGlobalCommittable)
+ assert(!inst.isInstanceOf[PolyParam], i"bad inst $this := $inst, constr = ${ctx.typerState.constraint}")
+
instantiateWith(inst)
}
diff --git a/tests/pending/pos/t8230a.scala b/tests/pos/t8230a.scala
index 405aa86f5..f878eacf8 100644
--- a/tests/pending/pos/t8230a.scala
+++ b/tests/pos/t8230a.scala
@@ -15,12 +15,12 @@ object Test {
object Okay {
Arr("1")
- import I.{ arrToTrav, longArrToTrav }
- foo(Arr("2"))
- }
+ import I.{ arrToTrav, longArrToTrav }
+ val x = foo(Arr("2"))
+ }
object Fail {
- import I.arrToTrav
- foo(Arr("3")) // found String, expected Long
+// import I.arrToTrav
+// foo(Arr("3")) // found String, expected Long
}
}