@@ -17,6 +17,7 @@ import Decorators._
1717import Uniques ._
1818import ErrorReporting .{errorType , DiagnosticString }
1919import config .Printers ._
20+ import annotation .tailrec
2021import collection .mutable
2122
2223trait Inferencing { this : Checking =>
@@ -43,9 +44,26 @@ trait Inferencing { this: Checking =>
4344 if (isFullyDefined(tp, ForceDegree .all)) tp
4445 else throw new Error (i " internal error: type of $what $tp is not fully defined, pos = $pos" ) // !!! DEBUG
4546
47+
48+ /** Instantiate selected type variables `tvars` in type `tp` */
49+ def instantiateSelected (tp : Type , tvars : List [Type ])(implicit ctx : Context ): Unit =
50+ new IsFullyDefinedAccumulator (new ForceDegree .Value (tvars.contains)).process(tp)
51+
4652 /** 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
53+ * and returns whether the type is fully defined. The direction in which
54+ * a type variable is instantiated is determined as follows:
55+ * 1. T is minimized if the constraint over T is only from below (i.e.
56+ * constrained lower bound != given lower bound and
57+ * constrained upper bound == given upper bound).
58+ * 2. T is maximized if the constraint over T is only from above (i.e.
59+ * constrained upper bound != given upper bound and
60+ * constrained lower bound == given lower bound).
61+ * If (1) and (2) do not apply:
62+ * 3. T is maximized if it appears only contravariantly in the given type.
63+ * 4. T is minimized in all other cases.
64+ *
65+ * The instantiation is done in two phases:
66+ * 1st Phase: Try to instantiate minimizable type variables to
4967 * their lower bound. Record whether successful.
5068 * 2nd Phase: If first phase was successful, instantiate all remaining type variables
5169 * to their upper bound.
@@ -61,14 +79,20 @@ trait Inferencing { this: Checking =>
6179 case _ : WildcardType | _ : ProtoType =>
6280 false
6381 case tvar : TypeVar if ! tvar.isInstantiated =>
64- if (force == ForceDegree .none) false
65- 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
82+ force.appliesTo(tvar) && {
83+ val direction = instDirection(tvar.origin)
84+ if (direction != 0 ) {
85+ if (direction > 0 ) println(s " inst $tvar dir = up " )
86+ instantiate(tvar, direction < 0 )
87+ }
88+ else {
89+ val minimize =
90+ variance >= 0 && ! (
91+ force == ForceDegree .noBottom &&
92+ isBottomType(ctx.typeComparer.approximation(tvar.origin, fromBelow = true )))
93+ if (minimize) instantiate(tvar, fromBelow = true )
94+ else toMaximize = true
95+ }
7296 foldOver(x, tvar)
7397 }
7498 case tp =>
@@ -93,6 +117,62 @@ trait Inferencing { this: Checking =>
93117 }
94118 }
95119
120+ /** The list of uninstantiated type variables bound by some prefix of type `T` which
121+ * occur in at least one formal parameter type of a prefix application.
122+ * Considered prefixes are:
123+ * - The function `f` of an application node `f(e1, .., en)`
124+ * - The function `f` of a type application node `f[T1, ..., Tn]`
125+ * - The prefix `p` of a selection `p.f`.
126+ * - The result expression `e` of a block `{s1; .. sn; e}`.
127+ */
128+ def tvarsInParams (tree : Tree )(implicit ctx : Context ): List [TypeVar ] = {
129+ @ tailrec def boundVars (tree : Tree , acc : List [TypeVar ]): List [TypeVar ] = tree match {
130+ case Apply (fn, _) => boundVars(fn, acc)
131+ case TypeApply (fn, targs) =>
132+ val tvars = targs.tpes.collect {
133+ case tvar : TypeVar if ! tvar.isInstantiated => tvar
134+ }
135+ boundVars(fn, acc ::: tvars)
136+ case Select (pre, _) => boundVars(pre, acc)
137+ case Block (_, expr) => boundVars(expr, acc)
138+ case _ => acc
139+ }
140+ @ tailrec def occurring (tree : Tree , toTest : List [TypeVar ], acc : List [TypeVar ]): List [TypeVar ] =
141+ if (toTest.isEmpty) acc
142+ else tree match {
143+ case Apply (fn, _) =>
144+ fn.tpe match {
145+ case mtp : MethodType =>
146+ val (occ, nocc) = toTest.partition(tvar => mtp.paramTypes.exists(tvar.occursIn))
147+ occurring(fn, nocc, occ ::: acc)
148+ case _ =>
149+ occurring(fn, toTest, acc)
150+ }
151+ case TypeApply (fn, targs) => occurring(fn, toTest, acc)
152+ case Select (pre, _) => occurring(pre, toTest, acc)
153+ case Block (_, expr) => occurring(expr, toTest, acc)
154+ case _ => acc
155+ }
156+ occurring(tree, boundVars(tree, Nil ), Nil )
157+ }
158+
159+ /** The instantiation direction for given poly param computed
160+ * from the constraint:
161+ * @return 1 (maximize) if constraint is uniformly from above,
162+ * -1 (minimize) if constraint is uniformly from below,
163+ * 0 if unconstrained, or constraint is from below and above.
164+ */
165+ private def instDirection (param : PolyParam )(implicit ctx : Context ): Int = {
166+ val constrained = ctx.typerState.constraint.fullBounds(param)
167+ val original = param.binder.paramBounds(param.paramNum)
168+ val cmp = ctx.typeComparer
169+ val approxBelow =
170+ if (! cmp.isSubTypeWhenFrozen(constrained.lo, original.lo)) 1 else 0
171+ val approxAbove =
172+ if (! cmp.isSubTypeWhenFrozen(original.hi, constrained.hi)) 1 else 0
173+ approxAbove - approxBelow
174+ }
175+
96176 def isBottomType (tp : Type )(implicit ctx : Context ) =
97177 tp == defn.NothingType || tp == defn.NullType
98178
@@ -257,9 +337,10 @@ trait Inferencing { this: Checking =>
257337}
258338
259339/** An enumeration controlling the degree of forcing in "is-dully-defined" checks. */
260- @ sharable object ForceDegree extends Enumeration {
261- val none, // don' t force type variables
262- noBottom, // force type variables, fail if forced to Nothing or Null
263- all = Value // force type variables, don't fail
340+ @ sharable object ForceDegree {
341+ class Value (val appliesTo : TypeVar => Boolean )
342+ val none = new Value (_ => false )
343+ val all = new Value (_ => true )
344+ val noBottom = new Value (_ => true )
264345}
265346
0 commit comments