@@ -44,8 +44,20 @@ trait Inferencing { this: Checking =>
44
44
else throw new Error (i " internal error: type of $what $tp is not fully defined, pos = $pos" ) // !!! DEBUG
45
45
46
46
/** The accumulator which forces type variables using the policy encoded in `force`
47
- * and returns whether the type is fully defined. Two phases:
48
- * 1st Phase: Try to instantiate covariant and non-variant type variables to
47
+ * and returns whether the type is fully defined. The direction in which
48
+ * a type variable is instantiated is determined as follows:
49
+ * 1. T is minimized if the constraint over T is only from below (i.e.
50
+ * constrained lower bound != given lower bound and
51
+ * constrained upper bound == given upper bound).
52
+ * 2. T is maximized if the constraint over T is only from above (i.e.
53
+ * constrained upper bound != given upper bound and
54
+ * constrained lower bound == given lower bound).
55
+ * If (1) and (2) do not apply:
56
+ * 3. T is maximized if it appears only contravariantly in the given type.
57
+ * 4. T is minimized in all other cases.
58
+ *
59
+ * The instantiation is done in two phases:
60
+ * 1st Phase: Try to instantiate minimizable type variables to
49
61
* their lower bound. Record whether successful.
50
62
* 2nd Phase: If first phase was successful, instantiate all remaining type variables
51
63
* to their upper bound.
@@ -63,12 +75,19 @@ trait Inferencing { this: Checking =>
63
75
case tvar : TypeVar if ! tvar.isInstantiated =>
64
76
if (force == ForceDegree .none) false
65
77
else {
66
- val minimize =
67
- variance >= 0 && ! (
68
- force == ForceDegree .noBottom &&
69
- isBottomType(ctx.typeComparer.approximation(tvar.origin, fromBelow = true )))
70
- if (minimize) instantiate(tvar, fromBelow = true )
71
- else toMaximize = true
78
+ val direction = instDirection(tvar.origin)
79
+ if (direction != 0 ) {
80
+ if (direction > 0 ) println(s " inst $tvar dir = up " )
81
+ instantiate(tvar, direction < 0 )
82
+ }
83
+ else {
84
+ val minimize =
85
+ variance >= 0 && ! (
86
+ force == ForceDegree .noBottom &&
87
+ isBottomType(ctx.typeComparer.approximation(tvar.origin, fromBelow = true )))
88
+ if (minimize) instantiate(tvar, fromBelow = true )
89
+ else toMaximize = true
90
+ }
72
91
foldOver(x, tvar)
73
92
}
74
93
case tp =>
@@ -93,6 +112,23 @@ trait Inferencing { this: Checking =>
93
112
}
94
113
}
95
114
115
+ /** The instantiation direction for given poly param computed
116
+ * from the constraint:
117
+ * @return 1 (maximize) if constraint is uniformly from above,
118
+ * -1 (minimize) if constraint is uniformly from below,
119
+ * 0 if unconstrained, or constraint is from below and above.
120
+ */
121
+ private def instDirection (param : PolyParam )(implicit ctx : Context ): Int = {
122
+ val constrained = ctx.typerState.constraint.fullBounds(param)
123
+ val original = param.binder.paramBounds(param.paramNum)
124
+ val cmp = ctx.typeComparer
125
+ val approxBelow =
126
+ if (! cmp.isSubTypeWhenFrozen(constrained.lo, original.lo)) 1 else 0
127
+ val approxAbove =
128
+ if (! cmp.isSubTypeWhenFrozen(original.hi, constrained.hi)) 1 else 0
129
+ approxAbove - approxBelow
130
+ }
131
+
96
132
def isBottomType (tp : Type )(implicit ctx : Context ) =
97
133
tp == defn.NothingType || tp == defn.NullType
98
134
0 commit comments