@@ -18,15 +18,18 @@ import config.Printers.{constr, typr}
18
18
* By comparison: Constraint handlers are parts of type comparers and can use their functionality.
19
19
* Constraint handlers update the current constraint as a side effect.
20
20
*/
21
- trait ConstraintHandling {
21
+ trait ConstraintHandling [ AbstractContext ] {
22
22
23
- implicit val ctx : Context
23
+ def constr_println (msg : => String ): Unit = constr.println(msg)
24
+ def typr_println (msg : => String ): Unit = typr.println(msg)
24
25
25
- protected def isSubType (tp1 : Type , tp2 : Type ): Boolean
26
- protected def isSameType (tp1 : Type , tp2 : Type ): Boolean
26
+ implicit def ctx (implicit ac : AbstractContext ): Context
27
27
28
- val state : TyperState
29
- import state .constraint
28
+ protected def isSubType (tp1 : Type , tp2 : Type )(implicit actx : AbstractContext ): Boolean
29
+ protected def isSameType (tp1 : Type , tp2 : Type )(implicit actx : AbstractContext ): Boolean
30
+
31
+ protected def constraint : Constraint
32
+ protected def constraint_= (c : Constraint ): Unit
30
33
31
34
private [this ] var addConstraintInvocations = 0
32
35
@@ -50,7 +53,20 @@ trait ConstraintHandling {
50
53
*/
51
54
protected var comparedTypeLambdas : Set [TypeLambda ] = Set .empty
52
55
53
- protected def addOneBound (param : TypeParamRef , bound : Type , isUpper : Boolean ): Boolean =
56
+ /** Gives for each instantiated type var that does not yet have its `inst` field
57
+ * set, the instance value stored in the constraint. Storing instances in constraints
58
+ * is done only in a temporary way for contexts that may be retracted
59
+ * without also retracting the type var as a whole.
60
+ */
61
+ def instType (tvar : TypeVar ): Type = constraint.entry(tvar.origin) match {
62
+ case _ : TypeBounds => NoType
63
+ case tp : TypeParamRef =>
64
+ var tvar1 = constraint.typeVarOfParam(tp)
65
+ if (tvar1.exists) tvar1 else tp
66
+ case tp => tp
67
+ }
68
+
69
+ protected def addOneBound (param : TypeParamRef , bound : Type , isUpper : Boolean )(implicit actx : AbstractContext ): Boolean =
54
70
! constraint.contains(param) || {
55
71
def occursIn (bound : Type ): Boolean = {
56
72
val b = bound.dealias
@@ -100,34 +116,34 @@ trait ConstraintHandling {
100
116
101
117
private def location (implicit ctx : Context ) = " " // i"in ${ctx.typerState.stateChainStr}" // use for debugging
102
118
103
- protected def addUpperBound (param : TypeParamRef , bound : Type ): Boolean = {
119
+ protected def addUpperBound (param : TypeParamRef , bound : Type )( implicit actx : AbstractContext ) : Boolean = {
104
120
def description = i " constraint $param <: $bound to \n $constraint"
105
121
if (bound.isRef(defn.NothingClass ) && ctx.typerState.isGlobalCommittable) {
106
122
def msg = s " !!! instantiated to Nothing: $param, constraint = ${constraint.show}"
107
123
if (Config .failOnInstantiationToNothing) assert(false , msg)
108
124
else ctx.log(msg)
109
125
}
110
- constr.println (i " adding $description$location" )
126
+ constr_println (i " adding $description$location" )
111
127
val lower = constraint.lower(param)
112
128
val res =
113
129
addOneBound(param, bound, isUpper = true ) &&
114
130
lower.forall(addOneBound(_, bound, isUpper = true ))
115
- constr.println (i " added $description = $res$location" )
131
+ constr_println (i " added $description = $res$location" )
116
132
res
117
133
}
118
134
119
- protected def addLowerBound (param : TypeParamRef , bound : Type ): Boolean = {
135
+ protected def addLowerBound (param : TypeParamRef , bound : Type )( implicit actx : AbstractContext ) : Boolean = {
120
136
def description = i " constraint $param >: $bound to \n $constraint"
121
- constr.println (i " adding $description" )
137
+ constr_println (i " adding $description" )
122
138
val upper = constraint.upper(param)
123
139
val res =
124
140
addOneBound(param, bound, isUpper = false ) &&
125
141
upper.forall(addOneBound(_, bound, isUpper = false ))
126
- constr.println (i " added $description = $res$location" )
142
+ constr_println (i " added $description = $res$location" )
127
143
res
128
144
}
129
145
130
- protected def addLess (p1 : TypeParamRef , p2 : TypeParamRef ): Boolean = {
146
+ protected def addLess (p1 : TypeParamRef , p2 : TypeParamRef )( implicit actx : AbstractContext ) : Boolean = {
131
147
def description = i " ordering $p1 <: $p2 to \n $constraint"
132
148
val res =
133
149
if (constraint.isLess(p2, p1)) unify(p2, p1)
@@ -136,20 +152,20 @@ trait ConstraintHandling {
136
152
val up2 = p2 :: constraint.exclusiveUpper(p2, p1)
137
153
val lo1 = constraint.nonParamBounds(p1).lo
138
154
val hi2 = constraint.nonParamBounds(p2).hi
139
- constr.println (i " adding $description down1 = $down1, up2 = $up2$location" )
155
+ constr_println (i " adding $description down1 = $down1, up2 = $up2$location" )
140
156
constraint = constraint.addLess(p1, p2)
141
157
down1.forall(addOneBound(_, hi2, isUpper = true )) &&
142
158
up2.forall(addOneBound(_, lo1, isUpper = false ))
143
159
}
144
- constr.println (i " added $description = $res$location" )
160
+ constr_println (i " added $description = $res$location" )
145
161
res
146
162
}
147
163
148
164
/** Make p2 = p1, transfer all bounds of p2 to p1
149
165
* @pre less(p1)(p2)
150
166
*/
151
- private def unify (p1 : TypeParamRef , p2 : TypeParamRef ): Boolean = {
152
- constr.println (s " unifying $p1 $p2" )
167
+ private def unify (p1 : TypeParamRef , p2 : TypeParamRef )( implicit actx : AbstractContext ) : Boolean = {
168
+ constr_println (s " unifying $p1 $p2" )
153
169
assert(constraint.isLess(p1, p2))
154
170
val down = constraint.exclusiveLower(p2, p1)
155
171
val up = constraint.exclusiveUpper(p1, p2)
@@ -163,7 +179,7 @@ trait ConstraintHandling {
163
179
}
164
180
165
181
166
- protected def isSubType (tp1 : Type , tp2 : Type , whenFrozen : Boolean ): Boolean = {
182
+ protected def isSubType (tp1 : Type , tp2 : Type , whenFrozen : Boolean )( implicit actx : AbstractContext ) : Boolean = {
167
183
if (whenFrozen)
168
184
isSubTypeWhenFrozen(tp1, tp2)
169
185
else
@@ -182,13 +198,13 @@ trait ConstraintHandling {
182
198
}
183
199
}
184
200
185
- final def isSubTypeWhenFrozen (tp1 : Type , tp2 : Type ): Boolean = inFrozenConstraint(isSubType(tp1, tp2))
186
- final def isSameTypeWhenFrozen (tp1 : Type , tp2 : Type ): Boolean = inFrozenConstraint(isSameType(tp1, tp2))
201
+ final def isSubTypeWhenFrozen (tp1 : Type , tp2 : Type )( implicit actx : AbstractContext ) : Boolean = inFrozenConstraint(isSubType(tp1, tp2))
202
+ final def isSameTypeWhenFrozen (tp1 : Type , tp2 : Type )( implicit actx : AbstractContext ) : Boolean = inFrozenConstraint(isSameType(tp1, tp2))
187
203
188
204
/** Test whether the lower bounds of all parameters in this
189
205
* constraint are a solution to the constraint.
190
206
*/
191
- protected final def isSatisfiable : Boolean =
207
+ protected final def isSatisfiable ( implicit actx : AbstractContext ) : Boolean =
192
208
constraint.forallParams { param =>
193
209
val TypeBounds (lo, hi) = constraint.entry(param)
194
210
isSubType(lo, hi) || {
@@ -207,7 +223,7 @@ trait ConstraintHandling {
207
223
* @return the instantiating type
208
224
* @pre `param` is in the constraint's domain.
209
225
*/
210
- final def approximation (param : TypeParamRef , fromBelow : Boolean ): Type = {
226
+ final def approximation (param : TypeParamRef , fromBelow : Boolean )( implicit actx : AbstractContext ) : Type = {
211
227
val avoidParam = new TypeMap {
212
228
override def stopAtStatic = true
213
229
def avoidInArg (arg : Type ): Type =
@@ -247,7 +263,7 @@ trait ConstraintHandling {
247
263
case _ : TypeBounds =>
248
264
val bound = if (fromBelow) constraint.fullLowerBound(param) else constraint.fullUpperBound(param)
249
265
val inst = avoidParam(bound)
250
- typr.println (s " approx ${param.show}, from below = $fromBelow, bound = ${bound.show}, inst = ${inst.show}" )
266
+ typr_println (s " approx ${param.show}, from below = $fromBelow, bound = ${bound.show}, inst = ${inst.show}" )
251
267
inst
252
268
case inst =>
253
269
assert(inst.exists, i " param = $param\n constraint = $constraint" )
@@ -261,7 +277,7 @@ trait ConstraintHandling {
261
277
* 2. If `tp` is a union type, yet upper bound is not a union type,
262
278
* approximate the union type from above by an intersection of all common base types.
263
279
*/
264
- def widenInferred (tp : Type , bound : Type ): Type = {
280
+ def widenInferred (tp : Type , bound : Type )( implicit actx : AbstractContext ) : Type = {
265
281
def isMultiSingleton (tp : Type ): Boolean = tp.stripAnnots match {
266
282
case tp : SingletonType => true
267
283
case AndType (tp1, tp2) => isMultiSingleton(tp1) | isMultiSingleton(tp2)
@@ -294,7 +310,7 @@ trait ConstraintHandling {
294
310
* a lower bound instantiation can be a singleton type only if the upper bound
295
311
* is also a singleton type.
296
312
*/
297
- def instanceType (param : TypeParamRef , fromBelow : Boolean ): Type = {
313
+ def instanceType (param : TypeParamRef , fromBelow : Boolean )( implicit actx : AbstractContext ) : Type = {
298
314
val inst = approximation(param, fromBelow).simplified
299
315
if (fromBelow) widenInferred(inst, constraint.fullUpperBound(param)) else inst
300
316
}
@@ -309,7 +325,7 @@ trait ConstraintHandling {
309
325
* Both `c1` and `c2` are required to derive from constraint `pre`, possibly
310
326
* narrowing it with further bounds.
311
327
*/
312
- protected final def subsumes (c1 : Constraint , c2 : Constraint , pre : Constraint ): Boolean =
328
+ protected final def subsumes (c1 : Constraint , c2 : Constraint , pre : Constraint )( implicit actx : AbstractContext ) : Boolean =
313
329
if (c2 eq pre) true
314
330
else if (c1 eq pre) false
315
331
else {
@@ -323,7 +339,7 @@ trait ConstraintHandling {
323
339
}
324
340
325
341
/** The current bounds of type parameter `param` */
326
- def bounds (param : TypeParamRef ): TypeBounds = {
342
+ def bounds (param : TypeParamRef )( implicit actx : AbstractContext ) : TypeBounds = {
327
343
val e = constraint.entry(param)
328
344
if (e.exists) e.bounds
329
345
else {
@@ -337,7 +353,7 @@ trait ConstraintHandling {
337
353
* and propagate all bounds.
338
354
* @param tvars See Constraint#add
339
355
*/
340
- def addToConstraint (tl : TypeLambda , tvars : List [TypeVar ]): Boolean =
356
+ def addToConstraint (tl : TypeLambda , tvars : List [TypeVar ])( implicit actx : AbstractContext ) : Boolean =
341
357
checkPropagated(i " initialized $tl" ) {
342
358
constraint = constraint.add(tl, tvars)
343
359
tl.paramRefs.forall { param =>
@@ -346,7 +362,7 @@ trait ConstraintHandling {
346
362
val lower = constraint.lower(param)
347
363
val upper = constraint.upper(param)
348
364
if (lower.nonEmpty && ! bounds.lo.isRef(defn.NothingClass ) ||
349
- upper.nonEmpty && ! bounds.hi.isRef(defn.AnyClass )) constr.println (i " INIT*** $tl" )
365
+ upper.nonEmpty && ! bounds.hi.isRef(defn.AnyClass )) constr_println (i " INIT*** $tl" )
350
366
lower.forall(addOneBound(_, bounds.hi, isUpper = true )) &&
351
367
upper.forall(addOneBound(_, bounds.lo, isUpper = false ))
352
368
case _ =>
@@ -365,7 +381,7 @@ trait ConstraintHandling {
365
381
* This holds if `TypeVarsMissContext` is set unless `param` is a part
366
382
* of a MatchType that is currently normalized.
367
383
*/
368
- final def assumedTrue (param : TypeParamRef ): Boolean =
384
+ final def assumedTrue (param : TypeParamRef )( implicit actx : AbstractContext ) : Boolean =
369
385
ctx.mode.is(Mode .TypevarsMissContext ) && (caseLambda `ne` param.binder)
370
386
371
387
/** Add constraint `param <: bound` if `fromBelow` is false, `param >: bound` otherwise.
@@ -375,7 +391,7 @@ trait ConstraintHandling {
375
391
* not be AndTypes and lower bounds may not be OrTypes. This is assured by the
376
392
* way isSubType is organized.
377
393
*/
378
- protected def addConstraint (param : TypeParamRef , bound : Type , fromBelow : Boolean ): Boolean = {
394
+ protected def addConstraint (param : TypeParamRef , bound : Type , fromBelow : Boolean )( implicit actx : AbstractContext ) : Boolean = {
379
395
def description = i " constr $param ${if (fromBelow) " >:" else " <:" } $bound: \n $constraint"
380
396
// checkPropagated(s"adding $description")(true) // DEBUG in case following fails
381
397
checkPropagated(s " added $description" ) {
@@ -491,7 +507,7 @@ trait ConstraintHandling {
491
507
}
492
508
493
509
/** Instantiate `param` to `tp` if the constraint stays satisfiable */
494
- protected def tryInstantiate (param : TypeParamRef , tp : Type ): Boolean = {
510
+ protected def tryInstantiate (param : TypeParamRef , tp : Type )( implicit actx : AbstractContext ) : Boolean = {
495
511
val saved = constraint
496
512
constraint =
497
513
if (addConstraint(param, tp, fromBelow = true ) &&
@@ -501,7 +517,7 @@ trait ConstraintHandling {
501
517
}
502
518
503
519
/** Check that constraint is fully propagated. See comment in Config.checkConstraintsPropagated */
504
- def checkPropagated (msg : => String )(result : Boolean ): Boolean = {
520
+ def checkPropagated (msg : => String )(result : Boolean )( implicit actx : AbstractContext ) : Boolean = {
505
521
if (Config .checkConstraintsPropagated && result && addConstraintInvocations == 0 ) {
506
522
inFrozenConstraint {
507
523
for (p <- constraint.domainParams) {
0 commit comments