@@ -35,6 +35,11 @@ trait ConstraintHandling {
35
35
/** If the constraint is frozen we cannot add new bounds to the constraint. */
36
36
protected var frozenConstraint = false
37
37
38
+ /** Potentially a type lambda that is still instantiatable, even though the constraint
39
+ * is generally frozen.
40
+ */
41
+ protected var caseLambda : Type = NoType
42
+
38
43
/** If set, align arguments `S1`, `S2`when taking the glb
39
44
* `T1 { X = S1 } & T2 { X = S2 }` of a constraint upper bound for some type parameter.
40
45
* Aligning means computing `S1 =:= S2` which may change the current constraint.
@@ -47,7 +52,7 @@ trait ConstraintHandling {
47
52
*/
48
53
protected var comparedTypeLambdas : Set [TypeLambda ] = Set .empty
49
54
50
- private def addOneBound (param : TypeParamRef , bound : Type , isUpper : Boolean ): Boolean =
55
+ protected def addOneBound (param : TypeParamRef , bound : Type , isUpper : Boolean ): Boolean =
51
56
! constraint.contains(param) || {
52
57
def occursIn (bound : Type ): Boolean = {
53
58
val b = bound.dealias
@@ -167,19 +172,20 @@ trait ConstraintHandling {
167
172
isSubType(tp1, tp2)
168
173
}
169
174
170
- final def isSubTypeWhenFrozen (tp1 : Type , tp2 : Type ): Boolean = {
171
- val saved = frozenConstraint
175
+ @ forceInline final def inFrozenConstraint [T ](op : => T ): T = {
176
+ val savedFrozen = frozenConstraint
177
+ val savedLambda = caseLambda
172
178
frozenConstraint = true
173
- try isSubType(tp1, tp2)
174
- finally frozenConstraint = saved
179
+ caseLambda = NoType
180
+ try op
181
+ finally {
182
+ frozenConstraint = savedFrozen
183
+ caseLambda = savedLambda
184
+ }
175
185
}
176
186
177
- final def isSameTypeWhenFrozen (tp1 : Type , tp2 : Type ): Boolean = {
178
- val saved = frozenConstraint
179
- frozenConstraint = true
180
- try isSameType(tp1, tp2)
181
- finally frozenConstraint = saved
182
- }
187
+ final def isSubTypeWhenFrozen (tp1 : Type , tp2 : Type ): Boolean = inFrozenConstraint(isSubType(tp1, tp2))
188
+ final def isSameTypeWhenFrozen (tp1 : Type , tp2 : Type ): Boolean = inFrozenConstraint(isSameType(tp1, tp2))
183
189
184
190
/** Test whether the lower bounds of all parameters in this
185
191
* constraint are a solution to the constraint.
@@ -319,7 +325,7 @@ trait ConstraintHandling {
319
325
}
320
326
321
327
/** The current bounds of type parameter `param` */
322
- final def bounds (param : TypeParamRef ): TypeBounds = {
328
+ def bounds (param : TypeParamRef ): TypeBounds = {
323
329
val e = constraint.entry(param)
324
330
if (e.exists) e.bounds
325
331
else {
@@ -355,7 +361,7 @@ trait ConstraintHandling {
355
361
356
362
/** Can `param` be constrained with new bounds? */
357
363
final def canConstrain (param : TypeParamRef ): Boolean =
358
- ! frozenConstraint && ( constraint contains param)
364
+ ( ! frozenConstraint || (caseLambda `eq` param.binder)) && constraint. contains( param)
359
365
360
366
/** Add constraint `param <: bound` if `fromBelow` is false, `param >: bound` otherwise.
361
367
* `bound` is assumed to be in normalized form, as specified in `firstTry` and
@@ -492,19 +498,18 @@ trait ConstraintHandling {
492
498
/** Check that constraint is fully propagated. See comment in Config.checkConstraintsPropagated */
493
499
def checkPropagated (msg : => String )(result : Boolean ): Boolean = {
494
500
if (Config .checkConstraintsPropagated && result && addConstraintInvocations == 0 ) {
495
- val saved = frozenConstraint
496
- frozenConstraint = true
497
- for (p <- constraint.domainParams) {
498
- def check (cond : => Boolean , q : TypeParamRef , ordering : String , explanation : String ) : Unit =
499
- assert(cond, i " propagation failure for $p $ordering $q : $explanation \n $msg " )
500
- for (u <- constraint.upper(p) )
501
- check(bounds(p).hi <:< bounds(u).hi, u, " <: " , " upper bound not propagated " )
502
- for (l <- constraint.lower (p)) {
503
- check(bounds(l).lo <:< bounds(p).hi , l, " >:" , " lower bound not propagated " )
504
- check(constraint.isLess(l, p), l, " >: " , " reverse ordering (<:) missing " )
501
+ inFrozenConstraint {
502
+ for (p <- constraint.domainParams) {
503
+ def check ( cond : => Boolean , q : TypeParamRef , ordering : String , explanation : String ) : Unit =
504
+ assert (cond, i " propagation failure for $p $ ordering $q : $explanation \n $msg " )
505
+ for (u <- constraint.upper(p) )
506
+ check(bounds(p).hi <:< bounds(u).hi, u, " <: " , " upper bound not propagated " )
507
+ for (l <- constraint.lower(p)) {
508
+ check(bounds(l).lo <:< bounds (p).hi, l, " >: " , " lower bound not propagated " )
509
+ check(constraint.isLess(l, p) , l, " >:" , " reverse ordering (<:) missing " )
510
+ }
505
511
}
506
512
}
507
- frozenConstraint = saved
508
513
}
509
514
result
510
515
}
0 commit comments