aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/core/Types.scala6
-rw-r--r--src/dotty/tools/dotc/typer/Inferencing.scala14
-rw-r--r--src/dotty/tools/dotc/typer/ProtoTypes.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala4
4 files changed, 19 insertions, 7 deletions
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 5f30f484e..f113307ef 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -2269,8 +2269,12 @@ object Types {
* @param creatorState The typer state in which the variable was created.
* @param owningTree The function part of the TypeApply tree tree that introduces
* the type variable.
+ * @paran owner The current owner if the context where the variable was created.
+ *
+ * `owningTree` and `owner` are used to determine whether a type-variable can be instantiated
+ * at some given point. See `Inferencing#interpolateUndetVars`.
*/
- final class TypeVar(val origin: PolyParam, creatorState: TyperState, val owningTree: untpd.Tree) extends CachedProxyType with ValueType {
+ final class TypeVar(val origin: PolyParam, creatorState: TyperState, val owningTree: untpd.Tree, val owner: Symbol) extends CachedProxyType with ValueType {
/** The permanent instance type of the the variable, or NoType is none is given yet */
private[core] var inst: Type = NoType
diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala
index 38c1e49c5..753125e6a 100644
--- a/src/dotty/tools/dotc/typer/Inferencing.scala
+++ b/src/dotty/tools/dotc/typer/Inferencing.scala
@@ -163,10 +163,18 @@ trait Inferencing { this: Checking =>
* If such a variable appears covariantly in type `tp` or does not appear at all,
* approximate it by its lower bound. Otherwise, if it appears contravariantly
* in type `tp` approximate it by its upper bound.
+ * @param ownedBy if it is different from NoSymbol, all type variables owned by
+ * `ownedBy` qualify, independent of position.
+ * Without that second condition, it can be that certain variables escape
+ * interpolation, for instance when their tree was eta-lifted, so
+ * the typechecked tree is no longer the tree in which the variable
+ * was declared. A concrete example of this phenomenon can be
+ * observed when compiling core.TypeOps#asSeenFrom.
*/
- def interpolateUndetVars(tree: Tree)(implicit ctx: Context): Unit = {
+ def interpolateUndetVars(tree: Tree, ownedBy: Symbol)(implicit ctx: Context): Unit = {
val constraint = ctx.typerState.constraint
- val qualifies = (tvar: TypeVar) => tree contains tvar.owningTree
+ val qualifies = (tvar: TypeVar) =>
+ (tree contains tvar.owningTree) || ownedBy.exists && tvar.owner == ownedBy
def interpolate() = Stats.track("interpolateUndetVars") {
val tp = tree.tpe.widen
constr.println(s"interpolate undet vars in ${tp.show}, pos = ${tree.pos}, mode = ${ctx.mode}, undets = ${constraint.uninstVars map (tvar => s"${tvar.show}@${tvar.owningTree.pos}")}")
@@ -182,7 +190,7 @@ trait Inferencing { this: Checking =>
}
}
if (changed) // instantiations might have uncovered new typevars to interpolate
- interpolateUndetVars(tree)
+ interpolateUndetVars(tree, ownedBy)
else
for (tvar <- constraint.uninstVars)
if (!(vs contains tvar) && qualifies(tvar)) {
diff --git a/src/dotty/tools/dotc/typer/ProtoTypes.scala b/src/dotty/tools/dotc/typer/ProtoTypes.scala
index c0e30b12e..f646f7ecd 100644
--- a/src/dotty/tools/dotc/typer/ProtoTypes.scala
+++ b/src/dotty/tools/dotc/typer/ProtoTypes.scala
@@ -326,7 +326,7 @@ object ProtoTypes {
def newTypeVars(pt: PolyType): List[TypeVar] =
for (n <- (0 until pt.paramNames.length).toList)
- yield new TypeVar(PolyParam(pt, n), state, owningTree)
+ yield new TypeVar(PolyParam(pt, n), state, owningTree, ctx.owner)
val added =
if (state.constraint contains pt) pt.duplicate(pt.paramNames, pt.paramBounds, pt.resultType)
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index e98b73cae..d194ccaae 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -1174,8 +1174,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def adapt(tree: Tree, pt: Type, original: untpd.Tree = untpd.EmptyTree)(implicit ctx: Context) = /*>|>*/ track("adapt") /*<|<*/ {
/*>|>*/ ctx.traceIndented(i"adapting $tree of type ${tree.tpe} to $pt", typr, show = true) /*<|<*/ {
- interpolateUndetVars(tree)
- tree overwriteType tree.tpe.simplified
+ interpolateUndetVars(tree, if (tree.isDef) tree.symbol else NoSymbol)
+ tree.overwriteType(tree.tpe.simplified)
adaptInterpolated(tree, pt, original)
}
}