@@ -43,10 +43,20 @@ object Inferencing {
4343 if (isFullyDefined(tp, ForceDegree .all)) tp
4444 else throw new Error (i " internal error: type of $what $tp is not fully defined, pos = $span" ) // !!! DEBUG
4545
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+ */
4755 def instantiateSelected (tp : Type , tvars : List [Type ])(implicit ctx : Context ): Unit =
4856 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)
5060
5161 /** Instantiate any type variables in `tp` whose bounds contain a reference to
5262 * one of the parameters in `tparams` or `vparamss`.
@@ -78,27 +88,35 @@ object Inferencing {
7888 * 2. T is maximized if the constraint over T is only from above (i.e.
7989 * constrained upper bound != given upper bound and
8090 * 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.
8691 *
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:
88105 * 1st Phase: Try to instantiate minimizable type variables to
89106 * their lower bound. Record whether successful.
90107 * 2nd Phase: If first phase was successful, instantiate all remaining type variables
91108 * to their upper bound.
92109 */
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 ] {
94112
95113 private def instantiate (tvar : TypeVar , fromBelow : Boolean ): Type = {
96114 val inst = tvar.instantiate(fromBelow)
97115 typr.println(i " forced instantiation of ${tvar.origin} = $inst" )
98116 inst
99117 }
100118
101- private var toMaximize : Boolean = false
119+ private var toMaximize : List [ TypeVar ] = Nil
102120
103121 def apply (x : Boolean , tp : Type ): Boolean = tp.dealias match {
104122 case _ : WildcardType | _ : ProtoType =>
@@ -108,34 +126,33 @@ object Inferencing {
108126 && ctx.typerState.constraint.contains(tvar)
109127 && {
110128 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
117139 foldOver(x, tvar)
118140 }
119141 case tp =>
120142 foldOver(x, tp)
121143 }
122144
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
127151 instantiate(tvar, fromBelow = false )
128- case _ =>
129- }
130- foldOver(x, tp)
131- }
132- }
133-
134- def process (tp : Type ): Boolean = {
152+ case nil =>
135153 val res = apply(true , tp)
136- if ( res && toMaximize) new UpperInstantiator ().apply((), tp )
154+ if res then maximize(toMaximize )
137155 res
138- }
139156 }
140157
141158 /** For all type parameters occurring in `tp`:
@@ -492,9 +509,9 @@ trait Inferencing { this: Typer =>
492509
493510/** An enumeration controlling the degree of forcing in "is-dully-defined" checks. */
494511@ 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 )
499516}
500517
0 commit comments