@@ -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,27 +88,35 @@ 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)
97
115
typr.println(i " forced instantiation of ${tvar.origin} = $inst" )
98
116
inst
99
117
}
100
118
101
- private var toMaximize : Boolean = false
119
+ private var toMaximize : List [ TypeVar ] = Nil
102
120
103
121
def apply (x : Boolean , tp : Type ): Boolean = tp.dealias match {
104
122
case _ : WildcardType | _ : ProtoType =>
@@ -108,34 +126,33 @@ 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) instantiate(tvar, fromBelow = true )
116
- else toMaximize = true
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
117
139
foldOver(x, tvar)
118
140
}
119
141
case tp =>
120
142
foldOver(x, tp)
121
143
}
122
144
123
- private class UpperInstantiator (implicit ctx : Context ) extends TypeAccumulator [Unit ] {
124
- def apply (x : Unit , tp : Type ): Unit = {
125
- tp match {
126
- case tvar : TypeVar if ! tvar.isInstantiated =>
145
+ def process (tp : Type ): Boolean =
146
+ // Maximize type vars in the order they were visited before */
147
+ def maximize (tvars : List [TypeVar ]): Unit = tvars match
148
+ case tvar :: tvars1 =>
149
+ maximize(tvars1)
150
+ if ! tvar.isInstantiated then
127
151
instantiate(tvar, fromBelow = false )
128
- case _ =>
129
- }
130
- foldOver(x, tp)
131
- }
132
- }
133
-
134
- def process (tp : Type ): Boolean = {
152
+ case nil =>
135
153
val res = apply(true , tp)
136
- if ( res && toMaximize) new UpperInstantiator ().apply((), tp )
154
+ if res then maximize(toMaximize )
137
155
res
138
- }
139
156
}
140
157
141
158
/** For all type parameters occurring in `tp`:
@@ -492,9 +509,9 @@ trait Inferencing { this: Typer =>
492
509
493
510
/** An enumeration controlling the degree of forcing in "is-dully-defined" checks. */
494
511
@ sharable object ForceDegree {
495
- class Value (val appliesTo : TypeVar => Boolean , val minimizeAll : Boolean , val allowBottom : Boolean = true )
496
- val none : Value = new Value (_ => false , minimizeAll = false )
497
- val all : Value = new Value (_ => true , minimizeAll = false )
498
- 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 )
499
516
}
500
517
0 commit comments