@@ -18,15 +18,18 @@ import config.Printers.{constr, typr}
1818 * By comparison: Constraint handlers are parts of type comparers and can use their functionality.
1919 * Constraint handlers update the current constraint as a side effect.
2020 */
21- trait ConstraintHandling {
21+ trait ConstraintHandling [ AbstractContext ] {
2222
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)
2425
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
2727
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
3033
3134 private [this ] var addConstraintInvocations = 0
3235
@@ -50,7 +53,20 @@ trait ConstraintHandling {
5053 */
5154 protected var comparedTypeLambdas : Set [TypeLambda ] = Set .empty
5255
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 =
5470 ! constraint.contains(param) || {
5571 def occursIn (bound : Type ): Boolean = {
5672 val b = bound.dealias
@@ -100,34 +116,34 @@ trait ConstraintHandling {
100116
101117 private def location (implicit ctx : Context ) = " " // i"in ${ctx.typerState.stateChainStr}" // use for debugging
102118
103- protected def addUpperBound (param : TypeParamRef , bound : Type ): Boolean = {
119+ protected def addUpperBound (param : TypeParamRef , bound : Type )( implicit actx : AbstractContext ) : Boolean = {
104120 def description = i " constraint $param <: $bound to \n $constraint"
105121 if (bound.isRef(defn.NothingClass ) && ctx.typerState.isGlobalCommittable) {
106122 def msg = s " !!! instantiated to Nothing: $param, constraint = ${constraint.show}"
107123 if (Config .failOnInstantiationToNothing) assert(false , msg)
108124 else ctx.log(msg)
109125 }
110- constr.println (i " adding $description$location" )
126+ constr_println (i " adding $description$location" )
111127 val lower = constraint.lower(param)
112128 val res =
113129 addOneBound(param, bound, isUpper = true ) &&
114130 lower.forall(addOneBound(_, bound, isUpper = true ))
115- constr.println (i " added $description = $res$location" )
131+ constr_println (i " added $description = $res$location" )
116132 res
117133 }
118134
119- protected def addLowerBound (param : TypeParamRef , bound : Type ): Boolean = {
135+ protected def addLowerBound (param : TypeParamRef , bound : Type )( implicit actx : AbstractContext ) : Boolean = {
120136 def description = i " constraint $param >: $bound to \n $constraint"
121- constr.println (i " adding $description" )
137+ constr_println (i " adding $description" )
122138 val upper = constraint.upper(param)
123139 val res =
124140 addOneBound(param, bound, isUpper = false ) &&
125141 upper.forall(addOneBound(_, bound, isUpper = false ))
126- constr.println (i " added $description = $res$location" )
142+ constr_println (i " added $description = $res$location" )
127143 res
128144 }
129145
130- protected def addLess (p1 : TypeParamRef , p2 : TypeParamRef ): Boolean = {
146+ protected def addLess (p1 : TypeParamRef , p2 : TypeParamRef )( implicit actx : AbstractContext ) : Boolean = {
131147 def description = i " ordering $p1 <: $p2 to \n $constraint"
132148 val res =
133149 if (constraint.isLess(p2, p1)) unify(p2, p1)
@@ -136,20 +152,20 @@ trait ConstraintHandling {
136152 val up2 = p2 :: constraint.exclusiveUpper(p2, p1)
137153 val lo1 = constraint.nonParamBounds(p1).lo
138154 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" )
140156 constraint = constraint.addLess(p1, p2)
141157 down1.forall(addOneBound(_, hi2, isUpper = true )) &&
142158 up2.forall(addOneBound(_, lo1, isUpper = false ))
143159 }
144- constr.println (i " added $description = $res$location" )
160+ constr_println (i " added $description = $res$location" )
145161 res
146162 }
147163
148164 /** Make p2 = p1, transfer all bounds of p2 to p1
149165 * @pre less(p1)(p2)
150166 */
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" )
153169 assert(constraint.isLess(p1, p2))
154170 val down = constraint.exclusiveLower(p2, p1)
155171 val up = constraint.exclusiveUpper(p1, p2)
@@ -163,7 +179,7 @@ trait ConstraintHandling {
163179 }
164180
165181
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 = {
167183 if (whenFrozen)
168184 isSubTypeWhenFrozen(tp1, tp2)
169185 else
@@ -182,13 +198,13 @@ trait ConstraintHandling {
182198 }
183199 }
184200
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))
187203
188204 /** Test whether the lower bounds of all parameters in this
189205 * constraint are a solution to the constraint.
190206 */
191- protected final def isSatisfiable : Boolean =
207+ protected final def isSatisfiable ( implicit actx : AbstractContext ) : Boolean =
192208 constraint.forallParams { param =>
193209 val TypeBounds (lo, hi) = constraint.entry(param)
194210 isSubType(lo, hi) || {
@@ -207,7 +223,7 @@ trait ConstraintHandling {
207223 * @return the instantiating type
208224 * @pre `param` is in the constraint's domain.
209225 */
210- final def approximation (param : TypeParamRef , fromBelow : Boolean ): Type = {
226+ final def approximation (param : TypeParamRef , fromBelow : Boolean )( implicit actx : AbstractContext ) : Type = {
211227 val avoidParam = new TypeMap {
212228 override def stopAtStatic = true
213229 def avoidInArg (arg : Type ): Type =
@@ -247,7 +263,7 @@ trait ConstraintHandling {
247263 case _ : TypeBounds =>
248264 val bound = if (fromBelow) constraint.fullLowerBound(param) else constraint.fullUpperBound(param)
249265 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}" )
251267 inst
252268 case inst =>
253269 assert(inst.exists, i " param = $param\n constraint = $constraint" )
@@ -261,7 +277,7 @@ trait ConstraintHandling {
261277 * 2. If `tp` is a union type, yet upper bound is not a union type,
262278 * approximate the union type from above by an intersection of all common base types.
263279 */
264- def widenInferred (tp : Type , bound : Type ): Type = {
280+ def widenInferred (tp : Type , bound : Type )( implicit actx : AbstractContext ) : Type = {
265281 def isMultiSingleton (tp : Type ): Boolean = tp.stripAnnots match {
266282 case tp : SingletonType => true
267283 case AndType (tp1, tp2) => isMultiSingleton(tp1) | isMultiSingleton(tp2)
@@ -294,7 +310,7 @@ trait ConstraintHandling {
294310 * a lower bound instantiation can be a singleton type only if the upper bound
295311 * is also a singleton type.
296312 */
297- def instanceType (param : TypeParamRef , fromBelow : Boolean ): Type = {
313+ def instanceType (param : TypeParamRef , fromBelow : Boolean )( implicit actx : AbstractContext ) : Type = {
298314 val inst = approximation(param, fromBelow).simplified
299315 if (fromBelow) widenInferred(inst, constraint.fullUpperBound(param)) else inst
300316 }
@@ -309,7 +325,7 @@ trait ConstraintHandling {
309325 * Both `c1` and `c2` are required to derive from constraint `pre`, possibly
310326 * narrowing it with further bounds.
311327 */
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 =
313329 if (c2 eq pre) true
314330 else if (c1 eq pre) false
315331 else {
@@ -323,7 +339,7 @@ trait ConstraintHandling {
323339 }
324340
325341 /** The current bounds of type parameter `param` */
326- def bounds (param : TypeParamRef ): TypeBounds = {
342+ def bounds (param : TypeParamRef )( implicit actx : AbstractContext ) : TypeBounds = {
327343 val e = constraint.entry(param)
328344 if (e.exists) e.bounds
329345 else {
@@ -337,7 +353,7 @@ trait ConstraintHandling {
337353 * and propagate all bounds.
338354 * @param tvars See Constraint#add
339355 */
340- def addToConstraint (tl : TypeLambda , tvars : List [TypeVar ]): Boolean =
356+ def addToConstraint (tl : TypeLambda , tvars : List [TypeVar ])( implicit actx : AbstractContext ) : Boolean =
341357 checkPropagated(i " initialized $tl" ) {
342358 constraint = constraint.add(tl, tvars)
343359 tl.paramRefs.forall { param =>
@@ -346,7 +362,7 @@ trait ConstraintHandling {
346362 val lower = constraint.lower(param)
347363 val upper = constraint.upper(param)
348364 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" )
350366 lower.forall(addOneBound(_, bounds.hi, isUpper = true )) &&
351367 upper.forall(addOneBound(_, bounds.lo, isUpper = false ))
352368 case _ =>
@@ -365,7 +381,7 @@ trait ConstraintHandling {
365381 * This holds if `TypeVarsMissContext` is set unless `param` is a part
366382 * of a MatchType that is currently normalized.
367383 */
368- final def assumedTrue (param : TypeParamRef ): Boolean =
384+ final def assumedTrue (param : TypeParamRef )( implicit actx : AbstractContext ) : Boolean =
369385 ctx.mode.is(Mode .TypevarsMissContext ) && (caseLambda `ne` param.binder)
370386
371387 /** Add constraint `param <: bound` if `fromBelow` is false, `param >: bound` otherwise.
@@ -375,7 +391,7 @@ trait ConstraintHandling {
375391 * not be AndTypes and lower bounds may not be OrTypes. This is assured by the
376392 * way isSubType is organized.
377393 */
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 = {
379395 def description = i " constr $param ${if (fromBelow) " >:" else " <:" } $bound: \n $constraint"
380396 // checkPropagated(s"adding $description")(true) // DEBUG in case following fails
381397 checkPropagated(s " added $description" ) {
@@ -491,7 +507,7 @@ trait ConstraintHandling {
491507 }
492508
493509 /** 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 = {
495511 val saved = constraint
496512 constraint =
497513 if (addConstraint(param, tp, fromBelow = true ) &&
@@ -501,7 +517,7 @@ trait ConstraintHandling {
501517 }
502518
503519 /** 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 = {
505521 if (Config .checkConstraintsPropagated && result && addConstraintInvocations == 0 ) {
506522 inFrozenConstraint {
507523 for (p <- constraint.domainParams) {
0 commit comments