@@ -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.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
262
249
! fail && (skip || foldOver(x, tvar))
263
250
}
264
251
case tp => foldOver(x, tp)
@@ -438,22 +425,20 @@ object Inferencing {
438
425
occurring(tree, boundVars(tree, Nil ), Nil )
439
426
}
440
427
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
457
442
458
443
/** Following type aliases and stripping refinements and annotations, if one arrives at a
459
444
* class type reference where the class has a companion module, a reference to
@@ -651,16 +636,17 @@ trait Inferencing { this: Typer =>
651
636
652
637
val ownedVars = state.ownedVars
653
638
if (ownedVars ne locked) && ! ownedVars.isEmpty then
654
- val qualifying = ownedVars -- locked
639
+ val qualifying = ( ownedVars -- locked).toList
655
640
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}" )
657
642
val resultAlreadyConstrained =
658
- tree.isInstanceOf [Apply ] || tree.tpe. isInstanceOf [ MethodOrPoly ]
643
+ tree.isInstanceOf [Apply ]
659
644
if (! resultAlreadyConstrained)
645
+ trace(i " constrainResult( $tree ${tree.symbol}, ${tree.tpe}, $pt) " ):
660
646
constrainResult(tree.symbol, tree.tpe, pt)
661
647
// This is needed because it could establish singleton type upper bounds. See i2998.scala.
662
648
663
- val tp = tree.tpe.widen
649
+ val tp = tree.tpe
664
650
val vs = variances(tp, pt)
665
651
666
652
// Avoid interpolating variables occurring in tree's type if typerstate has unreported errors.
@@ -687,6 +673,8 @@ trait Inferencing { this: Typer =>
687
673
688
674
def constraint = state.constraint
689
675
676
+ trace(i " interpolateTypeVars( $tree: ${tree.tpe}, $pt, $qualifying) " , typr, (_ : Any ) => i " $qualifying $constraint" ) {
677
+
690
678
/** Values of this type report type variables to instantiate with variance indication:
691
679
* +1 variable appears covariantly, can be instantiated from lower bound
692
680
* -1 variable appears contravariantly, can be instantiated from upper bound
@@ -782,12 +770,10 @@ trait Inferencing { this: Typer =>
782
770
/** Try to instantiate `tvs`, return any suspended type variables */
783
771
def tryInstantiate (tvs : ToInstantiate ): ToInstantiate = tvs match
784
772
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" )
788
773
if tvar.isInstantiated then
789
774
tryInstantiate(tvs1)
790
775
else
776
+ val fromBelow = instDecision(tvar.origin, v, false , IfBottom .flip) == Decision .Min
791
777
val suspend = tvs1.exists{ (following, _) =>
792
778
if fromBelow
793
779
then constraint.isLess(following.origin, tvar.origin)
@@ -797,13 +783,16 @@ trait Inferencing { this: Typer =>
797
783
typr.println(i " suspended: $hd" )
798
784
hd :: tryInstantiate(tvs1)
799
785
else
786
+ typr.println(
787
+ i " interpolate ${if v == 0 then " non-occurring" else " " } $tvar in $state in $tree: $tp, fromBelow = $fromBelow, $constraint" )
800
788
tvar.instantiate(fromBelow)
801
789
tryInstantiate(tvs1)
802
790
case Nil => Nil
803
791
if tvs.nonEmpty then doInstantiate(tryInstantiate(tvs))
804
792
end doInstantiate
805
793
806
794
doInstantiate(filterByDeps(toInstantiate))
795
+ }
807
796
}
808
797
end if
809
798
tree
0 commit comments