@@ -43,10 +43,20 @@ object Inferencing {
43
43
if (isFullyDefined(tp, ForceDegree .all)) tp
44
44
else throw new Error (i " internal error: type of $what $tp is not fully defined, pos = $span" ) // !!! DEBUG
45
45
46
- /** Instantiate selected type variables `tvars` in type `tp` */
46
+ /** Instantiate selected type variables `tvars` in type `tp` in a special mode:
47
+ * 1. If a type variable is constrained from below (i.e. constraint bound != given lower bound)
48
+ * it is minimized.
49
+ * 2. Otherwise, if the type variable is constrained from above, it is maximized.
50
+ * 3. Otherwise, if the type variable has a lower bound != Nothing, it is minimized.
51
+ * 4. Otherwise, if the type variable has an upper bound != Any, it is maximized.
52
+ * If none of (1) - (4) applies, the type variable is left uninstantiated.
53
+ * The method is called to instantiate type variables before an implicit search.
54
+ */
47
55
def instantiateSelected (tp : Type , tvars : List [Type ])(implicit ctx : Context ): Unit =
48
56
if (tvars.nonEmpty)
49
- new IsFullyDefinedAccumulator (new ForceDegree .Value (tvars.contains, minimizeAll = true , allowBottom = false )).process(tp)
57
+ IsFullyDefinedAccumulator (
58
+ ForceDegree .Value (tvars.contains, allowBottom = false ), minimizeSelected = true
59
+ ).process(tp)
50
60
51
61
/** Instantiate any type variables in `tp` whose bounds contain a reference to
52
62
* one of the parameters in `tparams` or `vparamss`.
@@ -78,19 +88,27 @@ object Inferencing {
78
88
* 2. T is maximized if the constraint over T is only from above (i.e.
79
89
* constrained upper bound != given upper bound and
80
90
* constrained lower bound == given lower bound).
81
- * If (1) and (2) do not apply:
82
- * 3. T is minimized if forceDegree is minimizeAll.
83
- * 4. Otherwise, T is maximized if it appears only contravariantly in the given type,
84
- * or if forceDegree is `noBottom` and T's minimized value is a bottom type.
85
- * 5. Otherwise, T is minimized.
86
91
*
87
- * The instantiation is done in two phases:
92
+ * If (1) and (2) do not apply, and minimizeSelected is set:
93
+ * 3. T is minimized if it has a lower bound (different from Nothing) in the
94
+ * current constraint (the bound might come from T's declaration).
95
+ * 4. Otherwise, T is maximized if it has an upper bound (different from Any)
96
+ * in the currented constraint (the bound might come from T's declaration).
97
+ * 5. Otherwise, T is not instantiated at all.
98
+
99
+ * If (1) and (2) do not apply, and minimizeSelected is not set:
100
+ * 6: T is maximized if it appears only contravariantly in the given type,
101
+ * or if forceDegree is `noBottom` and T has no lower bound different from Nothing.
102
+ * 7. Otherwise, T is minimized.
103
+ *
104
+ * The instantiation for (6) and (7) is done in two phases:
88
105
* 1st Phase: Try to instantiate minimizable type variables to
89
106
* their lower bound. Record whether successful.
90
107
* 2nd Phase: If first phase was successful, instantiate all remaining type variables
91
108
* to their upper bound.
92
109
*/
93
- private class IsFullyDefinedAccumulator (force : ForceDegree .Value )(implicit ctx : Context ) extends TypeAccumulator [Boolean ] {
110
+ private class IsFullyDefinedAccumulator (force : ForceDegree .Value , minimizeSelected : Boolean = false )
111
+ (implicit ctx : Context ) extends TypeAccumulator [Boolean ] {
94
112
95
113
private def instantiate (tvar : TypeVar , fromBelow : Boolean ): Type = {
96
114
val inst = tvar.instantiate(fromBelow)
@@ -108,14 +126,16 @@ object Inferencing {
108
126
&& ctx.typerState.constraint.contains(tvar)
109
127
&& {
110
128
val direction = instDirection(tvar.origin)
111
- def preferMin =
112
- force.minimizeAll && (tvar.hasLowerBound || ! tvar.hasUpperBound)
113
- || variance >= 0 && (force.allowBottom || tvar.hasLowerBound)
114
- if (direction != 0 ) instantiate(tvar, direction < 0 )
115
- else if (preferMin)
116
- if force.minimizeAll && ! tvar.hasLowerBound then () // do nothing
117
- else instantiate(tvar, fromBelow = true )
118
- else toMaximize = tvar :: toMaximize
129
+ if direction != 0 then
130
+ instantiate(tvar, fromBelow = direction < 0 )
131
+ else if minimizeSelected then
132
+ if tvar.hasLowerBound then instantiate(tvar, fromBelow = true )
133
+ else if tvar.hasUpperBound then instantiate(tvar, fromBelow = false )
134
+ else () // hold off instantiating unbounded unconstrained variables
135
+ else if variance >= 0 && (force.allowBottom || tvar.hasLowerBound) then
136
+ instantiate(tvar, fromBelow = true )
137
+ else
138
+ toMaximize = tvar :: toMaximize
119
139
foldOver(x, tvar)
120
140
}
121
141
case tp =>
@@ -489,9 +509,9 @@ trait Inferencing { this: Typer =>
489
509
490
510
/** An enumeration controlling the degree of forcing in "is-dully-defined" checks. */
491
511
@ sharable object ForceDegree {
492
- class Value (val appliesTo : TypeVar => Boolean , val minimizeAll : Boolean , val allowBottom : Boolean = true )
493
- val none : Value = new Value (_ => false , minimizeAll = false )
494
- val all : Value = new Value (_ => true , minimizeAll = false )
495
- val noBottom : Value = new Value (_ => true , minimizeAll = false , allowBottom = false )
512
+ class Value (val appliesTo : TypeVar => Boolean , val allowBottom : Boolean )
513
+ val none : Value = new Value (_ => false , allowBottom = true )
514
+ val all : Value = new Value (_ => true , allowBottom = true )
515
+ val noBottom : Value = new Value (_ => true , allowBottom = false )
496
516
}
497
517
0 commit comments