Skip to content

Commit 9ee8548

Browse files
committed
Cleanup commit
This commit cleans up a piece of code of scala#3774 (which is already merged). It was suggested in review comments.
1 parent 5b9c884 commit 9ee8548

File tree

1 file changed

+81
-0
lines changed

1 file changed

+81
-0
lines changed

compiler/src/dotty/tools/dotc/typer/Inferencing.scala

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,87 @@ object Inferencing {
375375
}
376376
}
377377

378+
trait Inferencing { this: Typer =>
379+
import Inferencing._
380+
import tpd._
381+
382+
/** Interpolate those undetermined type variables in the widened type of this tree
383+
* which are introduced by type application contained in the tree.
384+
* If such a variable appears covariantly in type `tp` or does not appear at all,
385+
* approximate it by its lower bound. Otherwise, if it appears contravariantly
386+
* in type `tp` approximate it by its upper bound.
387+
* @param ownedBy if it is different from NoSymbol, all type variables owned by
388+
* `ownedBy` qualify, independent of position.
389+
* Without that second condition, it can be that certain variables escape
390+
* interpolation, for instance when their tree was eta-lifted, so
391+
* the typechecked tree is no longer the tree in which the variable
392+
* was declared. A concrete example of this phenomenon can be
393+
* observed when compiling core.TypeOps#asSeenFrom.
394+
*/
395+
def interpolateUndetVars(tree: Tree, ownedBy: Symbol, pt: Type)(implicit ctx: Context): Unit = {
396+
val constraint = ctx.typerState.constraint
397+
val qualifies = (tvar: TypeVar) =>
398+
(tree contains tvar.bindingTree) || ownedBy.exists && tvar.owner == ownedBy
399+
def interpolate() = Stats.track("interpolateUndetVars") {
400+
val tp = tree.tpe.widen
401+
constr.println(s"interpolate undet vars in ${tp.show}, pos = ${tree.pos}, mode = ${ctx.mode}, undets = ${constraint.uninstVars map (tvar => s"${tvar.show}@${tvar.bindingTree.pos}")}")
402+
constr.println(s"qualifying undet vars: ${constraint.uninstVars filter qualifies map (tvar => s"$tvar / ${tvar.show}")}, constraint: ${constraint.show}")
403+
404+
val vs = variances(tp, qualifies)
405+
val hasUnreportedErrors = ctx.typerState.reporter match {
406+
case r: StoreReporter if r.hasErrors => true
407+
case _ => false
408+
}
409+
410+
var isConstrained = tree.isInstanceOf[Apply] || tree.tpe.isInstanceOf[MethodOrPoly]
411+
412+
def ensureConstrained() = if (!isConstrained) {
413+
isConstrained = true
414+
constrainResult(tree.tpe, pt)
415+
}
416+
417+
// Avoid interpolating variables if typerstate has unreported errors.
418+
// Reason: The errors might reflect unsatisfiable constraints. In that
419+
// case interpolating without taking account the constraints risks producing
420+
// nonsensical types that then in turn produce incomprehensible errors.
421+
// An example is in neg/i1240.scala. Without the condition in the next code line
422+
// we get for
423+
//
424+
// val y: List[List[String]] = List(List(1))
425+
//
426+
// i1430.scala:5: error: type mismatch:
427+
// found : Int(1)
428+
// required: Nothing
429+
// val y: List[List[String]] = List(List(1))
430+
// ^
431+
// With the condition, we get the much more sensical:
432+
//
433+
// i1430.scala:5: error: type mismatch:
434+
// found : Int(1)
435+
// required: String
436+
// val y: List[List[String]] = List(List(1))
437+
if (!hasUnreportedErrors)
438+
vs foreachBinding { (tvar, v) =>
439+
if (v != 0 && ctx.typerState.constraint.contains(tvar)) {
440+
// previous interpolations could have already instantiated `tvar`
441+
// through unification, that's why we have to check again whether `tvar`
442+
// is contained in the current constraint.
443+
typr.println(s"interpolate ${if (v == 1) "co" else "contra"}variant ${tvar.show} in ${tp.show}")
444+
ensureConstrained()
445+
tvar.instantiate(fromBelow = v == 1)
446+
}
447+
}
448+
for (tvar <- constraint.uninstVars)
449+
if (!(vs contains tvar) && qualifies(tvar)) {
450+
typr.println(s"instantiating non-occurring ${tvar.show} in ${tp.show} / $tp")
451+
ensureConstrained()
452+
tvar.instantiate(fromBelow = true)
453+
}
454+
}
455+
if (constraint.uninstVars exists qualifies) interpolate()
456+
}
457+
}
458+
378459
/** An enumeration controlling the degree of forcing in "is-dully-defined" checks. */
379460
@sharable object ForceDegree {
380461
class Value(val appliesTo: TypeVar => Boolean, val minimizeAll: Boolean)

0 commit comments

Comments
 (0)