@@ -240,25 +240,12 @@ object Inferencing {
240
240
&& {
241
241
var fail = false
242
242
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
262
249
! fail && (skip || foldOver(x, tvar))
263
250
}
264
251
case tp => foldOver(x, tp)
@@ -452,9 +439,32 @@ object Inferencing {
452
439
if (! cmp.isSubTypeWhenFrozen(constrained.lo, original.lo)) 1 else 0
453
440
val approxAbove =
454
441
if (! cmp.isSubTypeWhenFrozen(original.hi, constrained.hi)) 1 else 0
442
+ // println(i"instDirection($param) = $approxAbove - $approxBelow original=[$original] constrained=[$constrained]")
455
443
approxAbove - approxBelow
456
444
}
457
445
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
+
458
468
/** Following type aliases and stripping refinements and annotations, if one arrives at a
459
469
* class type reference where the class has a companion module, a reference to
460
470
* that companion module. Otherwise NoType
@@ -651,7 +661,7 @@ trait Inferencing { this: Typer =>
651
661
652
662
val ownedVars = state.ownedVars
653
663
if (ownedVars ne locked) && ! ownedVars.isEmpty then
654
- val qualifying = ownedVars -- locked
664
+ val qualifying = ( ownedVars -- locked).toList
655
665
if (! qualifying.isEmpty) {
656
666
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}" )
657
667
val resultAlreadyConstrained =
@@ -687,6 +697,10 @@ trait Inferencing { this: Typer =>
687
697
688
698
def constraint = state.constraint
689
699
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
+
690
704
/** Values of this type report type variables to instantiate with variance indication:
691
705
* +1 variable appears covariantly, can be instantiated from lower bound
692
706
* -1 variable appears contravariantly, can be instantiated from upper bound
@@ -804,6 +818,7 @@ trait Inferencing { this: Typer =>
804
818
end doInstantiate
805
819
806
820
doInstantiate(filterByDeps(toInstantiate))
821
+ }
807
822
}
808
823
end if
809
824
tree
0 commit comments