@@ -9,27 +9,14 @@ import config.Printers._
99
1010/** Methods for adding constraints and solving them.
1111 *
12- * Constraints are required to be in normalized form. This means
13- * (1) if P <: Q in C then also Q >: P in C
14- * (2) if P r Q in C and Q r R in C then also P r R in C, where r is <: or :>
15- *
16- * "P <: Q in C" means here: There is a constraint P <: H[Q],
17- * where H is the multi-hole context given by:
18- *
19- * H = []
20- * H & T
21- * T & H
22- * H | H
23- *
24- * (the idea is that a parameter Q in a H context is guaranteed to be a supertype of P).
25- *
26- * "P >: Q in C" means: There is a constraint P >: L[Q],
27- * where L is the multi-hole context given by:
28- *
29- * L = []
30- * L | T
31- * T | L
32- * L & L
12+ * What goes into a Constraint as opposed to a ConstrainHandler?
13+ *
14+ * Constraint code is purely functional: Operations get constraints and produce new ones.
15+ * Constraint code does not have access to a type-comparer. Anything regarding lubs and glbs has to be done
16+ * elsewhere.
17+ *
18+ * By comparison: Constraint handlers are parts of type comparers and can use their functionality.
19+ * Constraint handlers update the current constraint as a side effect.
3320 */
3421trait ConstraintHandling {
3522
@@ -59,7 +46,7 @@ trait ConstraintHandling {
5946 def description = i " constraint $param <: $bound to \n $constraint"
6047 if (bound.isRef(defn.NothingClass ) && ctx.typerState.isGlobalCommittable) {
6148 def msg = s " !!! instantiated to Nothing: $param, constraint = ${constraint.show}"
62- if (Config .flagInstantiationToNothing ) assert(false , msg)
49+ if (Config .failOnInstantiationToNothing ) assert(false , msg)
6350 else ctx.log(msg)
6451 }
6552 constr.println(i " adding $description" )
@@ -86,9 +73,6 @@ trait ConstraintHandling {
8673 def description = i " ordering $p1 <: $p2 to \n $constraint"
8774 val res =
8875 if (constraint.isLess(p2, p1)) unify(p2, p1)
89- // !!! this is direction dependent - unify(p1, p2) makes i94-nada loop forever.
90- // Need to investigate why this is the case.
91- // The symptom is that we get a subtyping constraint of the form P { ... } <: P
9276 else {
9377 val down1 = p1 :: constraint.exclusiveLower(p1, p2)
9478 val up2 = p2 :: constraint.exclusiveUpper(p2, p1)
@@ -193,20 +177,24 @@ trait ConstraintHandling {
193177 case _ => param.binder.paramBounds(param.paramNum)
194178 }
195179
196- /** If `p` is a parameter of `pt`, propagate the non-parameter bounds
197- * of `p` to the parameters known to be less or greater than `p`.
180+ /** Add polytype `pt`, possibly with type variables `tvars`, to current constraint
181+ * and propagate all bounds.
182+ * @param tvars See Constraint#add
198183 */
199- def initialize (pt : PolyType ): Boolean =
200- checkPropagated(i " initialized $pt" ) {
201- pt.paramNames.indices.forall { i =>
202- val param = PolyParam (pt, i)
203- val bounds = constraint.nonParamBounds(param)
204- val lower = constraint.lower(param)
205- val upper = constraint.upper(param)
206- if (lower.nonEmpty && ! bounds.lo.isRef(defn.NothingClass ) ||
207- upper.nonEmpty && ! bounds.hi.isRef(defn.AnyClass )) println(i " INIT*** $pt" )
208- lower.forall(addOneBound(_, bounds.hi, isUpper = true )) &&
209- upper.forall(addOneBound(_, bounds.lo, isUpper = false ))
184+ def addToConstraint (pt : PolyType , tvars : List [TypeVar ]): Unit =
185+ assert {
186+ checkPropagated(i " initialized $pt" ) {
187+ constraint = constraint.add(pt, tvars)
188+ pt.paramNames.indices.forall { i =>
189+ val param = PolyParam (pt, i)
190+ val bounds = constraint.nonParamBounds(param)
191+ val lower = constraint.lower(param)
192+ val upper = constraint.upper(param)
193+ if (lower.nonEmpty && ! bounds.lo.isRef(defn.NothingClass ) ||
194+ upper.nonEmpty && ! bounds.hi.isRef(defn.AnyClass )) println(i " INIT*** $pt" )
195+ lower.forall(addOneBound(_, bounds.hi, isUpper = true )) &&
196+ upper.forall(addOneBound(_, bounds.lo, isUpper = false ))
197+ }
210198 }
211199 }
212200
@@ -238,6 +226,7 @@ trait ConstraintHandling {
238226 /** Check that constraint is fully propagated. See comment in Config.checkConstraintsPropagated */
239227 def checkPropagated (msg : => String )(result : Boolean ): Boolean = {
240228 if (Config .checkConstraintsPropagated && result && addConstraintInvocations == 0 ) {
229+ val saved = frozenConstraint
241230 frozenConstraint = true
242231 for (p <- constraint.domainParams) {
243232 def check (cond : => Boolean , q : PolyParam , ordering : String , explanation : String ): Unit =
@@ -249,7 +238,7 @@ trait ConstraintHandling {
249238 check(constraint.isLess(l, p), l, " >:" , " reverse ordering (<:) missing" )
250239 }
251240 }
252- frozenConstraint = false
241+ frozenConstraint = saved
253242 }
254243 result
255244 }
0 commit comments