@@ -178,25 +178,12 @@ object Inferencing {
178178 && ctx.typerState.constraint.contains(tvar)
179179 && {
180180 var fail = false
181- val direction = instDirection(tvar.origin)
182- if minimizeSelected then
183- if direction <= 0 && tvar.hasLowerBound then
184- instantiate(tvar, fromBelow = true )
185- else if direction >= 0 && tvar.hasUpperBound then
186- instantiate(tvar, fromBelow = false )
187- // else hold off instantiating unbounded unconstrained variable
188- else if direction != 0 then
189- instantiate(tvar, fromBelow = direction < 0 )
190- else if variance >= 0 && tvar.hasLowerBound then
191- instantiate(tvar, fromBelow = true )
192- else if (variance > 0 || variance == 0 && ! tvar.hasUpperBound)
193- && force.ifBottom == IfBottom .ok
194- then // if variance == 0, prefer upper bound if one is given
195- instantiate(tvar, fromBelow = true )
196- else if variance >= 0 && force.ifBottom == IfBottom .fail then
197- fail = true
198- else
199- toMaximize = tvar :: toMaximize
181+ instDecision(tvar, variance, minimizeSelected, force.ifBottom) match
182+ case Decision .Min => instantiate(tvar, fromBelow = true )
183+ case Decision .Max => instantiate(tvar, fromBelow = false )
184+ case Decision .Skip => // hold off instantiating unbounded unconstrained variable
185+ case Decision .Fail => fail = true
186+ case Decision .ToMax => toMaximize ::= tvar
200187 ! fail && foldOver(x, tvar)
201188 }
202189 case tp => foldOver(x, tp)
@@ -385,9 +372,32 @@ object Inferencing {
385372 if (! cmp.isSubTypeWhenFrozen(constrained.lo, original.lo)) 1 else 0
386373 val approxAbove =
387374 if (! cmp.isSubTypeWhenFrozen(original.hi, constrained.hi)) 1 else 0
375+ // println(i"instDirection($param) = $approxAbove - $approxBelow original=[$original] constrained=[$constrained]")
388376 approxAbove - approxBelow
389377 }
390378
379+ /** The instantiation decision for given poly param computed from the constraint. */
380+ enum Decision { case Min ; case Max ; case ToMax ; case Skip ; case Fail }
381+ private def instDecision (tvar : TypeVar , v : Int , minimizeSelected : Boolean , ifBottom : IfBottom )(using Context ): Decision =
382+ import Decision .*
383+ val direction = instDirection(tvar.origin)
384+ val dec = if minimizeSelected then
385+ if direction <= 0 && tvar.hasLowerBound then Min
386+ else if direction >= 0 && tvar.hasUpperBound then Max
387+ else Skip
388+ else if direction != 0 then if direction < 0 then Min else Max
389+ else if tvar.hasLowerBound then if v >= 0 then Min else ToMax
390+ else ifBottom match
391+ // What's left are unconstrained tvars with at most a non-Any param upperbound:
392+ // * IfBottom.flip will always maximise to the param upperbound, for all variances
393+ // * IfBottom.fail will fail the IFD check, for covariant or invariant tvars, maximise contravariant tvars
394+ // * IfBottom.ok will minimise to Nothing covariant and unbounded invariant tvars, and max to Any the others
395+ case IfBottom .ok => if v > 0 || v == 0 && ! tvar.hasUpperBound then Min else ToMax // prefer upper bound if one is given
396+ case IfBottom .fail => if v >= 0 then Fail else ToMax
397+ case ifBottom_flip => ToMax
398+ // println(i"instDecision($tvar, v=v, minimizedSelected=$minimizeSelected, $ifBottom) dir=$direction = $dec")
399+ dec
400+
391401 /** Following type aliases and stripping refinements and annotations, if one arrives at a
392402 * class type reference where the class has a companion module, a reference to
393403 * that companion module. Otherwise NoType
@@ -584,7 +594,7 @@ trait Inferencing { this: Typer =>
584594
585595 val ownedVars = state.ownedVars
586596 if (ownedVars ne locked) && ! ownedVars.isEmpty then
587- val qualifying = ownedVars -- locked
597+ val qualifying = ( ownedVars -- locked).toList
588598 if (! qualifying.isEmpty) {
589599 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}" )
590600 val resultAlreadyConstrained =
@@ -620,6 +630,10 @@ trait Inferencing { this: Typer =>
620630
621631 def constraint = state.constraint
622632
633+ trace(i " interpolateTypeVars( $tree: ${tree.tpe}, $pt, $qualifying) " , typr, (_ : Any ) => i " $qualifying\n $constraint\n ${ctx.gadt}" ) {
634+ // println(i"$constraint")
635+ // println(i"${ctx.gadt}")
636+
623637 /** Values of this type report type variables to instantiate with variance indication:
624638 * +1 variable appears covariantly, can be instantiated from lower bound
625639 * -1 variable appears contravariantly, can be instantiated from upper bound
@@ -737,6 +751,7 @@ trait Inferencing { this: Typer =>
737751 end doInstantiate
738752
739753 doInstantiate(filterByDeps(toInstantiate))
754+ }
740755 }
741756 end if
742757 tree
0 commit comments