@@ -81,16 +81,26 @@ trait ConstraintHandling {
81
81
assert(homogenizeArgs == false )
82
82
assert(comparedTypeLambdas == Set .empty)
83
83
84
- def nestingLevel (param : TypeParamRef ) = constraint.typeVarOfParam(param) match
84
+ def nestingLevel (param : TypeParamRef )( using Context ) = constraint.typeVarOfParam(param) match
85
85
case tv : TypeVar => tv.nestingLevel
86
- case _ => Int .MaxValue
86
+ case _ =>
87
+ // This should only happen when reducing match types or in uncommitable TyperStates
88
+ // (as asserted in ProtoTypes.constrained) and is special-cased in `levelOK` below.
89
+ Int .MaxValue
90
+
91
+ /** Is `level` <= `maxLevel` or legal in the current context? */
92
+ def levelOK (level : Int , maxLevel : Int )(using Context ): Boolean =
93
+ level <= maxLevel ||
94
+ ctx.isAfterTyper || ! ctx.typerState.isCommittable || // Leaks in these cases shouldn't break soundness
95
+ level == Int .MaxValue // See `nestingLevel` above.
87
96
88
97
/** If `param` is nested deeper than `maxLevel`, try to instantiate it to a
89
98
* fresh type variable of level `maxLevel` and return the new variable.
90
99
* If this isn't possible, throw a TypeError.
91
100
*/
92
101
def atLevel (maxLevel : Int , param : TypeParamRef )(using Context ): TypeParamRef =
93
- if nestingLevel(param) <= maxLevel then return param
102
+ if levelOK(nestingLevel(param), maxLevel) then
103
+ return param
94
104
LevelAvoidMap (0 , maxLevel)(param) match
95
105
case freshVar : TypeVar => freshVar.origin
96
106
case _ => throw new TypeError (
@@ -129,18 +139,12 @@ trait ConstraintHandling {
129
139
130
140
/** An approximating map that prevents types nested deeper than maxLevel as
131
141
* 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.
134
142
*/
135
143
class LevelAvoidMap (topLevelVariance : Int , maxLevel : Int )(using Context ) extends TypeOps .AvoidMap :
136
144
variance = topLevelVariance
137
145
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
-
142
146
def toAvoid (tp : NamedType ): Boolean =
143
- tp.prefix == NoPrefix && ! tp.symbol.isStatic && ! levelOK(tp.symbol.nestingLevel)
147
+ tp.prefix == NoPrefix && ! tp.symbol.isStatic && ! levelOK(tp.symbol.nestingLevel, maxLevel )
144
148
145
149
/** Return a (possibly fresh) type variable of a level no greater than `maxLevel` which is:
146
150
* - lower-bounded by `tp` if variance >= 0
@@ -185,7 +189,7 @@ trait ConstraintHandling {
185
189
end legalVar
186
190
187
191
override def apply (tp : Type ): Type = tp match
188
- case tp : TypeVar if ! tp.isInstantiated && ! levelOK(tp.nestingLevel) =>
192
+ case tp : TypeVar if ! tp.isInstantiated && ! levelOK(tp.nestingLevel, maxLevel ) =>
189
193
legalVar(tp)
190
194
// TypeParamRef can occur in tl bounds
191
195
case tp : TypeParamRef =>
@@ -431,7 +435,6 @@ trait ConstraintHandling {
431
435
final def approximation (param : TypeParamRef , fromBelow : Boolean )(using Context ): Type =
432
436
constraint.entry(param) match
433
437
case entry : TypeBounds =>
434
- val maxLevel = nestingLevel(param)
435
438
val useLowerBound = fromBelow || param.occursIn(entry.hi)
436
439
val inst = if useLowerBound then fullLowerBound(param) else fullUpperBound(param)
437
440
typr.println(s " approx ${param.show}, from below = $fromBelow, inst = ${inst.show}" )
0 commit comments