@@ -482,14 +482,9 @@ trait ConstraintHandling {
482
482
* and computes on the side sets of nested type variables that need
483
483
* to be instantiated.
484
484
*/
485
- class NeedsLeveling extends TypeAccumulator [Boolean ]:
485
+ def needsLeveling = new TypeAccumulator [Boolean ]:
486
486
if ! fromBelow then variance = - 1
487
487
488
- /** Nested type variables that should be instiated to theor lower (respoctively
489
- * upper) bounds.
490
- */
491
- var nestedVarsLo, nestedVarsHi : SimpleIdentitySet [TypeVar ] = SimpleIdentitySet .empty
492
-
493
488
def apply (need : Boolean , tp : Type ) =
494
489
need || tp.match
495
490
case tp : NamedType =>
@@ -499,39 +494,30 @@ trait ConstraintHandling {
499
494
val inst = tp.instanceOpt
500
495
if inst.exists then apply(need, inst)
501
496
else if tp.nestingLevel > maxLevel then
502
- if variance > 0 then nestedVarsLo += tp
503
- else if variance < 0 then nestedVarsHi += tp
504
- else
505
- // For invariant type variables, we use a different strategy.
506
- // Rather than instantiating to a bound and then propagating in an
507
- // AvoidMap, change the nesting level of an invariant type
508
- // variable to `maxLevel`. This means that the type variable will be
509
- // instantiated later to a less nested type. If there are other references
510
- // to the same type variable that do not come from the type undergoing
511
- // `fixLevels`, this could lead to coarser types. But it has the potential
512
- // to give a better approximation for the current type, since it avoids forming
513
- // a Range in invariant position, which can lead to very coarse types further out.
514
- constr.println(i " widening nesting level of type variable $tp from ${tp.nestingLevel} to $maxLevel" )
515
- ctx.typerState.setNestingLevel(tp, maxLevel)
497
+ // Change the nesting level of inner type variable to `maxLevel`.
498
+ // This means that the type variable will be instantiated later to a
499
+ // less nested type. If there are other references to the same type variable
500
+ // that do not come from the type undergoing `fixLevels`, this could lead
501
+ // to coarser types than intended. An alternative is to instantiate the
502
+ // type variable right away, but this also loses information. See
503
+ // i15934.scala for a test where the current strategey works but an early instantiation
504
+ // of `tp` would fail.
505
+ constr.println(i " widening nesting level of type variable $tp from ${tp.nestingLevel} to $maxLevel" )
506
+ ctx.typerState.setNestingLevel(tp, maxLevel)
516
507
true
517
508
else false
518
509
case _ =>
519
510
foldOver(need, tp)
520
- end NeedsLeveling
511
+ end needsLeveling
521
512
522
- class LevelAvoidMap extends TypeOps .AvoidMap :
513
+ def levelAvoid = new TypeOps .AvoidMap :
523
514
if ! fromBelow then variance = - 1
524
515
def toAvoid (tp : NamedType ) = needsFix(tp)
525
516
526
- if ! Config .checkLevelsOnInstantiation || ctx.isAfterTyper then tp
527
- else
528
- val needsLeveling = NeedsLeveling ()
529
- if needsLeveling(false , tp) then
530
- typr.println(i " instance $tp for $param needs leveling to $maxLevel, nested = ${needsLeveling.nestedVarsLo.toList} | ${needsLeveling.nestedVarsHi.toList}" )
531
- needsLeveling.nestedVarsLo.foreach(_.instantiate(fromBelow = true ))
532
- needsLeveling.nestedVarsHi.foreach(_.instantiate(fromBelow = false ))
533
- LevelAvoidMap ()(tp)
534
- else tp
517
+ if Config .checkLevelsOnInstantiation && ! ctx.isAfterTyper && needsLeveling(false , tp) then
518
+ typr.println(i " instance $tp for $param needs leveling to $maxLevel" )
519
+ levelAvoid(tp)
520
+ else tp
535
521
end fixLevels
536
522
537
523
/** Solve constraint set for given type parameter `param`.
0 commit comments