diff options
author | Martin Odersky <odersky@gmail.com> | 2015-09-18 17:37:56 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2015-09-18 17:37:56 +0200 |
commit | 493fbbdd6cd0ca7fecd7e34f963563fe58e1f877 (patch) | |
tree | 83c2e69cf63d3d08919862a2f608361259264444 /src/dotty/tools/dotc/typer/Inferencing.scala | |
parent | 7a97e86c71090600397fd9b14a5a4111c52d8498 (diff) | |
download | dotty-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.scala | 44 |
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) } |