@@ -240,25 +240,12 @@ object Inferencing {
240240 && {
241241 var fail = false
242242 var skip = false
243- val direction = instDirection(tvar.origin)
244- if minimizeSelected then
245- if direction <= 0 && tvar.hasLowerBound then
246- skip = instantiate(tvar, fromBelow = true )
247- else if direction >= 0 && tvar.hasUpperBound then
248- skip = instantiate(tvar, fromBelow = false )
249- // else hold off instantiating unbounded unconstrained variable
250- else if direction != 0 then
251- skip = instantiate(tvar, fromBelow = direction < 0 )
252- else if variance >= 0 && tvar.hasLowerBound then
253- skip = instantiate(tvar, fromBelow = true )
254- else if (variance > 0 || variance == 0 && ! tvar.hasUpperBound)
255- && force.ifBottom == IfBottom .ok
256- then // if variance == 0, prefer upper bound if one is given
257- skip = instantiate(tvar, fromBelow = true )
258- else if variance >= 0 && force.ifBottom == IfBottom .fail then
259- fail = true
260- else
261- toMaximize = tvar :: toMaximize
243+ instDecision(tvar.origin, variance, minimizeSelected, force.ifBottom) match
244+ case Decision .Min => skip = instantiate(tvar, fromBelow = true )
245+ case Decision .Max => skip = instantiate(tvar, fromBelow = false )
246+ case Decision .Skip => // hold off instantiating unbounded unconstrained variable
247+ case Decision .Fail => fail = true
248+ case Decision .ToMax => toMaximize ::= tvar
262249 ! fail && (skip || foldOver(x, tvar))
263250 }
264251 case tp => foldOver(x, tp)
@@ -438,22 +425,20 @@ object Inferencing {
438425 occurring(tree, boundVars(tree, Nil ), Nil )
439426 }
440427
441- /** The instantiation direction for given poly param computed
442- * from the constraint:
443- * @return 1 (maximize) if constraint is uniformly from above,
444- * -1 (minimize) if constraint is uniformly from below,
445- * 0 if unconstrained, or constraint is from below and above.
446- */
447- private def instDirection (param : TypeParamRef )(using Context ): Int = {
448- val constrained = TypeComparer .fullBounds(param)
449- val original = param.binder.paramInfos(param.paramNum)
450- val cmp = TypeComparer
451- val approxBelow =
452- if (! cmp.isSubTypeWhenFrozen(constrained.lo, original.lo)) 1 else 0
453- val approxAbove =
454- if (! cmp.isSubTypeWhenFrozen(original.hi, constrained.hi)) 1 else 0
455- approxAbove - approxBelow
456- }
428+ /** The instantiation decision for given poly param computed from the constraint. */
429+ enum Decision { case Min ; case Max ; case ToMax ; case Skip ; case Fail }
430+ private def instDecision (param : TypeParamRef , v : Int , min : Boolean , ifBottom : IfBottom )(using Context ): Decision =
431+ import Decision .*
432+ val tb = param.paramInfo // type bounds
433+ val cb = TypeComparer .fullBounds(param) // constrained bounds
434+ val dir = (if cb.lo frozen_<:< tb.lo then 0 else - 1 ) + (if tb.hi frozen_<:< cb.hi then 0 else 1 )
435+ if dir < 0 || (min || v >= 0 ) && ! cb.lo.isExactlyNothing then Min
436+ else if dir > 0 || (min || v == 0 ) && ! cb.hi.isTopOfSomeKind then Max // prefer upper bound if one is given
437+ else if min then Skip
438+ else ifBottom match
439+ case IfBottom .ok => if v >= 0 then Min else ToMax
440+ case IfBottom .fail => if v >= 0 then Fail else ToMax
441+ case ifBottom_flip => ToMax
457442
458443 /** Following type aliases and stripping refinements and annotations, if one arrives at a
459444 * class type reference where the class has a companion module, a reference to
@@ -651,16 +636,17 @@ trait Inferencing { this: Typer =>
651636
652637 val ownedVars = state.ownedVars
653638 if (ownedVars ne locked) && ! ownedVars.isEmpty then
654- val qualifying = ownedVars -- locked
639+ val qualifying = ( ownedVars -- locked).toList
655640 if (! qualifying.isEmpty) {
656- typr.println(i " interpolate $tree: ${tree.tpe.widen} in $state, pt = $pt, owned vars = ${state. ownedVars.toList}%, %, qualifying = ${ qualifying.toList}%, % , previous = ${locked.toList}%, % / ${state.constraint}" )
641+ typr.println(i " interpolate $tree: ${tree.tpe.widen} in $state, pt = $pt, owned vars = ${ownedVars.toList}, qualifying = $qualifying.toList}, previous = ${locked.toList}%, % / ${state.constraint}" )
657642 val resultAlreadyConstrained =
658- tree.isInstanceOf [Apply ] || tree.tpe. isInstanceOf [ MethodOrPoly ]
643+ tree.isInstanceOf [Apply ]
659644 if (! resultAlreadyConstrained)
645+ trace(i " constrainResult( $tree ${tree.symbol}, ${tree.tpe}, $pt) " ):
660646 constrainResult(tree.symbol, tree.tpe, pt)
661647 // This is needed because it could establish singleton type upper bounds. See i2998.scala.
662648
663- val tp = tree.tpe.widen
649+ val tp = tree.tpe
664650 val vs = variances(tp, pt)
665651
666652 // Avoid interpolating variables occurring in tree's type if typerstate has unreported errors.
@@ -687,6 +673,8 @@ trait Inferencing { this: Typer =>
687673
688674 def constraint = state.constraint
689675
676+ trace(i " interpolateTypeVars( $tree: ${tree.tpe}, $pt, $qualifying) " , typr, (_ : Any ) => i " $qualifying $constraint" ) {
677+
690678 /** Values of this type report type variables to instantiate with variance indication:
691679 * +1 variable appears covariantly, can be instantiated from lower bound
692680 * -1 variable appears contravariantly, can be instantiated from upper bound
@@ -782,12 +770,10 @@ trait Inferencing { this: Typer =>
782770 /** Try to instantiate `tvs`, return any suspended type variables */
783771 def tryInstantiate (tvs : ToInstantiate ): ToInstantiate = tvs match
784772 case (hd @ (tvar, v)) :: tvs1 =>
785- val fromBelow = v == 1 || (v == 0 && tvar.hasLowerBound)
786- typr.println(
787- i " interpolate ${if v == 0 then " non-occurring" else " " } $tvar in $state in $tree: $tp, fromBelow = $fromBelow, $constraint" )
788773 if tvar.isInstantiated then
789774 tryInstantiate(tvs1)
790775 else
776+ val fromBelow = instDecision(tvar.origin, v, false , IfBottom .flip) == Decision .Min
791777 val suspend = tvs1.exists{ (following, _) =>
792778 if fromBelow
793779 then constraint.isLess(following.origin, tvar.origin)
@@ -797,13 +783,16 @@ trait Inferencing { this: Typer =>
797783 typr.println(i " suspended: $hd" )
798784 hd :: tryInstantiate(tvs1)
799785 else
786+ typr.println(
787+ i " interpolate ${if v == 0 then " non-occurring" else " " } $tvar in $state in $tree: $tp, fromBelow = $fromBelow, $constraint" )
800788 tvar.instantiate(fromBelow)
801789 tryInstantiate(tvs1)
802790 case Nil => Nil
803791 if tvs.nonEmpty then doInstantiate(tryInstantiate(tvs))
804792 end doInstantiate
805793
806794 doInstantiate(filterByDeps(toInstantiate))
795+ }
807796 }
808797 end if
809798 tree
0 commit comments