@@ -9,27 +9,14 @@ import config.Printers._
9
9
10
10
/** Methods for adding constraints and solving them.
11
11
*
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.
33
20
*/
34
21
trait ConstraintHandling {
35
22
@@ -59,7 +46,7 @@ trait ConstraintHandling {
59
46
def description = i " constraint $param <: $bound to \n $constraint"
60
47
if (bound.isRef(defn.NothingClass ) && ctx.typerState.isGlobalCommittable) {
61
48
def msg = s " !!! instantiated to Nothing: $param, constraint = ${constraint.show}"
62
- if (Config .flagInstantiationToNothing ) assert(false , msg)
49
+ if (Config .failOnInstantiationToNothing ) assert(false , msg)
63
50
else ctx.log(msg)
64
51
}
65
52
constr.println(i " adding $description" )
@@ -86,9 +73,6 @@ trait ConstraintHandling {
86
73
def description = i " ordering $p1 <: $p2 to \n $constraint"
87
74
val res =
88
75
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
92
76
else {
93
77
val down1 = p1 :: constraint.exclusiveLower(p1, p2)
94
78
val up2 = p2 :: constraint.exclusiveUpper(p2, p1)
@@ -193,20 +177,24 @@ trait ConstraintHandling {
193
177
case _ => param.binder.paramBounds(param.paramNum)
194
178
}
195
179
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
198
183
*/
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
+ }
210
198
}
211
199
}
212
200
@@ -238,6 +226,7 @@ trait ConstraintHandling {
238
226
/** Check that constraint is fully propagated. See comment in Config.checkConstraintsPropagated */
239
227
def checkPropagated (msg : => String )(result : Boolean ): Boolean = {
240
228
if (Config .checkConstraintsPropagated && result && addConstraintInvocations == 0 ) {
229
+ val saved = frozenConstraint
241
230
frozenConstraint = true
242
231
for (p <- constraint.domainParams) {
243
232
def check (cond : => Boolean , q : PolyParam , ordering : String , explanation : String ): Unit =
@@ -249,7 +238,7 @@ trait ConstraintHandling {
249
238
check(constraint.isLess(l, p), l, " >:" , " reverse ordering (<:) missing" )
250
239
}
251
240
}
252
- frozenConstraint = false
241
+ frozenConstraint = saved
253
242
}
254
243
result
255
244
}
0 commit comments