@@ -482,14 +482,9 @@ trait ConstraintHandling {
482482 * and computes on the side sets of nested type variables that need
483483 * to be instantiated.
484484 */
485- class NeedsLeveling extends TypeAccumulator [Boolean ]:
485+ def needsLeveling = new TypeAccumulator [Boolean ]:
486486 if ! fromBelow then variance = - 1
487487
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-
493488 def apply (need : Boolean , tp : Type ) =
494489 need || tp.match
495490 case tp : NamedType =>
@@ -499,39 +494,30 @@ trait ConstraintHandling {
499494 val inst = tp.instanceOpt
500495 if inst.exists then apply(need, inst)
501496 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)
516507 true
517508 else false
518509 case _ =>
519510 foldOver(need, tp)
520- end NeedsLeveling
511+ end needsLeveling
521512
522- class LevelAvoidMap extends TypeOps .AvoidMap :
513+ def levelAvoid = new TypeOps .AvoidMap :
523514 if ! fromBelow then variance = - 1
524515 def toAvoid (tp : NamedType ) = needsFix(tp)
525516
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
535521 end fixLevels
536522
537523 /** Solve constraint set for given type parameter `param`.
0 commit comments