@@ -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, 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)
@@ -452,9 +439,32 @@ object Inferencing {
452439 if (! cmp.isSubTypeWhenFrozen(constrained.lo, original.lo)) 1 else 0
453440 val approxAbove =
454441 if (! cmp.isSubTypeWhenFrozen(original.hi, constrained.hi)) 1 else 0
442+ // println(i"instDirection($param) = $approxAbove - $approxBelow original=[$original] constrained=[$constrained]")
455443 approxAbove - approxBelow
456444 }
457445
446+ /** The instantiation decision for given poly param computed from the constraint. */
447+ enum Decision { case Min ; case Max ; case ToMax ; case Skip ; case Fail }
448+ private def instDecision (tvar : TypeVar , v : Int , minimizeSelected : Boolean , ifBottom : IfBottom )(using Context ): Decision =
449+ import Decision .*
450+ val direction = instDirection(tvar.origin)
451+ val dec = if minimizeSelected then
452+ if direction <= 0 && tvar.hasLowerBound then Min
453+ else if direction >= 0 && tvar.hasUpperBound then Max
454+ else Skip
455+ else if direction != 0 then if direction < 0 then Min else Max
456+ else if tvar.hasLowerBound then if v >= 0 then Min else ToMax
457+ else ifBottom match
458+ // What's left are unconstrained tvars with at most a non-Any param upperbound:
459+ // * IfBottom.flip will always maximise to the param upperbound, for all variances
460+ // * IfBottom.fail will fail the IFD check, for covariant or invariant tvars, maximise contravariant tvars
461+ // * IfBottom.ok will minimise to Nothing covariant and unbounded invariant tvars, and max to Any the others
462+ case IfBottom .ok => if v > 0 || v == 0 && ! tvar.hasUpperBound then Min else ToMax // prefer upper bound if one is given
463+ case IfBottom .fail => if v >= 0 then Fail else ToMax
464+ case ifBottom_flip => ToMax
465+ // println(i"instDecision($tvar, v=v, minimizedSelected=$minimizeSelected, $ifBottom) dir=$direction = $dec")
466+ dec
467+
458468 /** Following type aliases and stripping refinements and annotations, if one arrives at a
459469 * class type reference where the class has a companion module, a reference to
460470 * that companion module. Otherwise NoType
@@ -651,7 +661,7 @@ trait Inferencing { this: Typer =>
651661
652662 val ownedVars = state.ownedVars
653663 if (ownedVars ne locked) && ! ownedVars.isEmpty then
654- val qualifying = ownedVars -- locked
664+ val qualifying = ( ownedVars -- locked).toList
655665 if (! qualifying.isEmpty) {
656666 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}" )
657667 val resultAlreadyConstrained =
@@ -687,6 +697,10 @@ trait Inferencing { this: Typer =>
687697
688698 def constraint = state.constraint
689699
700+ trace(i " interpolateTypeVars( $tree: ${tree.tpe}, $pt, $qualifying) " , typr, (_ : Any ) => i " $qualifying\n $constraint\n ${ctx.gadt}" ) {
701+ // println(i"$constraint")
702+ // println(i"${ctx.gadt}")
703+
690704 /** Values of this type report type variables to instantiate with variance indication:
691705 * +1 variable appears covariantly, can be instantiated from lower bound
692706 * -1 variable appears contravariantly, can be instantiated from upper bound
@@ -804,6 +818,7 @@ trait Inferencing { this: Typer =>
804818 end doInstantiate
805819
806820 doInstantiate(filterByDeps(toInstantiate))
821+ }
807822 }
808823 end if
809824 tree
0 commit comments