aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/typer/Inferencing.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-09-18 17:37:56 +0200
committerMartin Odersky <odersky@gmail.com>2015-09-18 17:37:56 +0200
commit493fbbdd6cd0ca7fecd7e34f963563fe58e1f877 (patch)
tree83c2e69cf63d3d08919862a2f608361259264444 /src/dotty/tools/dotc/typer/Inferencing.scala
parent7a97e86c71090600397fd9b14a5a4111c52d8498 (diff)
downloaddotty-493fbbdd6cd0ca7fecd7e34f963563fe58e1f877.tar.gz
dotty-493fbbdd6cd0ca7fecd7e34f963563fe58e1f877.tar.bz2
dotty-493fbbdd6cd0ca7fecd7e34f963563fe58e1f877.zip
Fixes #739
by adding the following rule: Before typing an implicit parameter list of a method m, instantiate all type parameters of m that occur in the type of some preceding value parameter of m.
Diffstat (limited to 'src/dotty/tools/dotc/typer/Inferencing.scala')
-rw-r--r--src/dotty/tools/dotc/typer/Inferencing.scala44
1 files changed, 38 insertions, 6 deletions
diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala
index 6c8bf49ef..a5cf8c4eb 100644
--- a/src/dotty/tools/dotc/typer/Inferencing.scala
+++ b/src/dotty/tools/dotc/typer/Inferencing.scala
@@ -43,6 +43,11 @@ trait Inferencing { this: Checking =>
if (isFullyDefined(tp, ForceDegree.all)) tp
else throw new Error(i"internal error: type of $what $tp is not fully defined, pos = $pos") // !!! DEBUG
+
+ /** Instantiate selected type variables `tvars` in type `tp` */
+ def instantiateSelected(tp: Type, tvars: List[Type])(implicit ctx: Context): Unit =
+ new IsFullyDefinedAccumulator(new ForceDegree.Value(tvars.contains)).process(tp)
+
/** The accumulator which forces type variables using the policy encoded in `force`
* and returns whether the type is fully defined. The direction in which
* a type variable is instantiated is determined as follows:
@@ -73,8 +78,7 @@ trait Inferencing { this: Checking =>
case _: WildcardType | _: ProtoType =>
false
case tvar: TypeVar if !tvar.isInstantiated =>
- if (force == ForceDegree.none) false
- else {
+ force.appliesTo(tvar) && {
val direction = instDirection(tvar.origin)
if (direction != 0) {
if (direction > 0) println(s"inst $tvar dir = up")
@@ -111,6 +115,33 @@ trait Inferencing { this: Checking =>
res
}
}
+
+ /** If `tree`'s type is of the form
+ *
+ * e [T1, ..., Tn] (ps1)...(psn)
+ *
+ * the list of uninstantiated type variables matching one of `T1`, ..., `Tn`
+ * which also appear in one of the parameter sections `ps1`, ..., `psn`, otherwise Nil.
+ */
+ def tvarsInParams(tree: Tree)(implicit ctx: Context): List[TypeVar] = {
+ def occursInParam(mtp: Type, tvar: TypeVar, secCount: Int): Boolean = mtp match {
+ case mtp: MethodType =>
+ secCount > 0 && (
+ mtp.paramTypes.exists(tvar.occursIn) ||
+ occursInParam(mtp.resultType, tvar, secCount - 1))
+ case _ => false
+ }
+ def collect(tree: Tree, secCount: Int): List[TypeVar] = tree match {
+ case Apply(fn, _) => collect(fn, secCount + 1)
+ case TypeApply(_, targs) =>
+ targs.tpes.collect {
+ case tvar: TypeVar
+ if !tvar.isInstantiated && occursInParam(tree.tpe, tvar, secCount) => tvar
+ }
+ case _ => Nil
+ }
+ collect(tree, 0)
+ }
/** The instantiation direction for given poly param computed
* from the constraint:
@@ -293,9 +324,10 @@ trait Inferencing { this: Checking =>
}
/** An enumeration controlling the degree of forcing in "is-dully-defined" checks. */
-@sharable object ForceDegree extends Enumeration {
- val none, // don't force type variables
- noBottom, // force type variables, fail if forced to Nothing or Null
- all = Value // force type variables, don't fail
+@sharable object ForceDegree {
+ class Value(val appliesTo: TypeVar => Boolean)
+ val none = new Value(_ => false)
+ val all = new Value(_ => true)
+ val noBottom = new Value(_ => true)
}