@@ -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 =>
@@ -115,32 +116,44 @@ trait Inferencing { this: Checking =>
115116 res
116117 }
117118 }
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}`.
125127 */
126128 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
140134 }
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
142139 }
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 )
144157 }
145158
146159 /** The instantiation direction for given poly param computed
0 commit comments