@@ -81,16 +81,28 @@ trait ConstraintHandling {
8181 assert(homogenizeArgs == false )
8282 assert(comparedTypeLambdas == Set .empty)
8383
84- def nestingLevel (param : TypeParamRef ) = constraint.typeVarOfParam(param) match
84+ def nestingLevel (param : TypeParamRef )( using Context ) = constraint.typeVarOfParam(param) match
8585 case tv : TypeVar => tv.nestingLevel
86- case _ => Int .MaxValue
86+ case _ =>
87+ // This should only happen when reducing match types (in
88+ // TrackingTypeComparer#matchCases) or in uncommitable TyperStates (as
89+ // asserted in ProtoTypes.constrained) and is special-cased in `levelOK`
90+ // below.
91+ Int .MaxValue
92+
93+ /** Is `level` <= `maxLevel` or legal in the current context? */
94+ def levelOK (level : Int , maxLevel : Int )(using Context ): Boolean =
95+ level <= maxLevel ||
96+ ctx.isAfterTyper || ! ctx.typerState.isCommittable || // Leaks in these cases shouldn't break soundness
97+ level == Int .MaxValue // See `nestingLevel` above.
8798
8899 /** If `param` is nested deeper than `maxLevel`, try to instantiate it to a
89100 * fresh type variable of level `maxLevel` and return the new variable.
90101 * If this isn't possible, throw a TypeError.
91102 */
92103 def atLevel (maxLevel : Int , param : TypeParamRef )(using Context ): TypeParamRef =
93- if nestingLevel(param) <= maxLevel then return param
104+ if levelOK(nestingLevel(param), maxLevel) then
105+ return param
94106 LevelAvoidMap (0 , maxLevel)(param) match
95107 case freshVar : TypeVar => freshVar.origin
96108 case _ => throw new TypeError (
@@ -129,18 +141,12 @@ trait ConstraintHandling {
129141
130142 /** An approximating map that prevents types nested deeper than maxLevel as
131143 * well as WildcardTypes from leaking into the constraint.
132- * Note that level-checking is turned off after typer and in uncommitable
133- * TyperState since these leaks should be safe.
134144 */
135145 class LevelAvoidMap (topLevelVariance : Int , maxLevel : Int )(using Context ) extends TypeOps .AvoidMap :
136146 variance = topLevelVariance
137147
138- /** Are we allowed to refer to types of the given `level`? */
139- private def levelOK (level : Int ): Boolean =
140- level <= maxLevel || ctx.isAfterTyper || ! ctx.typerState.isCommittable
141-
142148 def toAvoid (tp : NamedType ): Boolean =
143- tp.prefix == NoPrefix && ! tp.symbol.isStatic && ! levelOK(tp.symbol.nestingLevel)
149+ tp.prefix == NoPrefix && ! tp.symbol.isStatic && ! levelOK(tp.symbol.nestingLevel, maxLevel )
144150
145151 /** Return a (possibly fresh) type variable of a level no greater than `maxLevel` which is:
146152 * - lower-bounded by `tp` if variance >= 0
@@ -185,7 +191,7 @@ trait ConstraintHandling {
185191 end legalVar
186192
187193 override def apply (tp : Type ): Type = tp match
188- case tp : TypeVar if ! tp.isInstantiated && ! levelOK(tp.nestingLevel) =>
194+ case tp : TypeVar if ! tp.isInstantiated && ! levelOK(tp.nestingLevel, maxLevel ) =>
189195 legalVar(tp)
190196 // TypeParamRef can occur in tl bounds
191197 case tp : TypeParamRef =>
@@ -431,7 +437,6 @@ trait ConstraintHandling {
431437 final def approximation (param : TypeParamRef , fromBelow : Boolean )(using Context ): Type =
432438 constraint.entry(param) match
433439 case entry : TypeBounds =>
434- val maxLevel = nestingLevel(param)
435440 val useLowerBound = fromBelow || param.occursIn(entry.hi)
436441 val inst = if useLowerBound then fullLowerBound(param) else fullUpperBound(param)
437442 typr.println(s " approx ${param.show}, from below = $fromBelow, inst = ${inst.show}" )
0 commit comments