@@ -17,6 +17,7 @@ import Decorators._
17
17
import Uniques ._
18
18
import ErrorReporting .{errorType , DiagnosticString }
19
19
import config .Printers ._
20
+ import annotation .tailrec
20
21
import collection .mutable
21
22
22
23
trait Inferencing { this : Checking =>
@@ -115,32 +116,44 @@ trait Inferencing { this: Checking =>
115
116
res
116
117
}
117
118
}
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.
119
+
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}`.
125
127
*/
126
128
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
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
140
134
}
141
- case _ => Nil
135
+ boundVars(fn, acc ::: tvars)
136
+ case Select (pre, _) => boundVars(pre, acc)
137
+ case Block (_, expr) => boundVars(expr, acc)
138
+ case _ => acc
142
139
}
143
- collect(tree, 0 )
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 )
144
157
}
145
158
146
159
/** The instantiation direction for given poly param computed
0 commit comments