@@ -43,6 +43,11 @@ trait Inferencing { this: Checking =>
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 = $pos" ) // !!! DEBUG
45
45
46
+
47
+ /** Instantiate selected type variables `tvars` in type `tp` */
48
+ def instantiateSelected (tp : Type , tvars : List [Type ])(implicit ctx : Context ): Unit =
49
+ new IsFullyDefinedAccumulator (new ForceDegree .Value (tvars.contains)).process(tp)
50
+
46
51
/** The accumulator which forces type variables using the policy encoded in `force`
47
52
* and returns whether the type is fully defined. The direction in which
48
53
* a type variable is instantiated is determined as follows:
@@ -73,8 +78,7 @@ trait Inferencing { this: Checking =>
73
78
case _ : WildcardType | _ : ProtoType =>
74
79
false
75
80
case tvar : TypeVar if ! tvar.isInstantiated =>
76
- if (force == ForceDegree .none) false
77
- else {
81
+ force.appliesTo(tvar) && {
78
82
val direction = instDirection(tvar.origin)
79
83
if (direction != 0 ) {
80
84
if (direction > 0 ) println(s " inst $tvar dir = up " )
@@ -111,6 +115,33 @@ trait Inferencing { this: Checking =>
111
115
res
112
116
}
113
117
}
118
+
119
+ /** If `tree`'s type is of the form
120
+ *
121
+ * e [T1, ..., Tn] (ps1)...(psn)
122
+ *
123
+ * the list of uninstantiated type variables matching one of `T1`, ..., `Tn`
124
+ * which also appear in one of the parameter sections `ps1`, ..., `psn`, otherwise Nil.
125
+ */
126
+ def tvarsInParams (tree : Tree )(implicit ctx : Context ): List [TypeVar ] = {
127
+ def occursInParam (mtp : Type , tvar : TypeVar , secCount : Int ): Boolean = mtp match {
128
+ case mtp : MethodType =>
129
+ secCount > 0 && (
130
+ mtp.paramTypes.exists(tvar.occursIn) ||
131
+ occursInParam(mtp.resultType, tvar, secCount - 1 ))
132
+ case _ => false
133
+ }
134
+ def collect (tree : Tree , secCount : Int ): List [TypeVar ] = tree match {
135
+ case Apply (fn, _) => collect(fn, secCount + 1 )
136
+ case TypeApply (_, targs) =>
137
+ targs.tpes.collect {
138
+ case tvar : TypeVar
139
+ if ! tvar.isInstantiated && occursInParam(tree.tpe, tvar, secCount) => tvar
140
+ }
141
+ case _ => Nil
142
+ }
143
+ collect(tree, 0 )
144
+ }
114
145
115
146
/** The instantiation direction for given poly param computed
116
147
* from the constraint:
@@ -293,9 +324,10 @@ trait Inferencing { this: Checking =>
293
324
}
294
325
295
326
/** An enumeration controlling the degree of forcing in "is-dully-defined" checks. */
296
- @ sharable object ForceDegree extends Enumeration {
297
- val none, // don' t force type variables
298
- noBottom, // force type variables, fail if forced to Nothing or Null
299
- all = Value // force type variables, don't fail
327
+ @ sharable object ForceDegree {
328
+ class Value (val appliesTo : TypeVar => Boolean )
329
+ val none = new Value (_ => false )
330
+ val all = new Value (_ => true )
331
+ val noBottom = new Value (_ => true )
300
332
}
301
333
0 commit comments