diff options
author | Martin Odersky <odersky@gmail.com> | 2016-08-01 14:37:57 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-08-16 17:32:54 +0200 |
commit | d2120ca8accb7d6b8438431931c84870e835512c (patch) | |
tree | 651c495bd7c92061500118c550eddb16422c7a52 /src | |
parent | a57b4a3ec5b139711ad7e729040165e58751a49c (diff) | |
download | dotty-d2120ca8accb7d6b8438431931c84870e835512c.tar.gz dotty-d2120ca8accb7d6b8438431931c84870e835512c.tar.bz2 dotty-d2120ca8accb7d6b8438431931c84870e835512c.zip |
Suspend interpolating typevars when there are unreported errors.
Interpolating typevars that appear co- or contra-variantly in a type
is a cleanup measure - it helps keep the constraint set small. However,
if there are uneported errors, some of these errors might report on
unsatisfiable constraints for these type variables. In that case, instantiating
the type variables risks being confusing.
Diffstat (limited to 'src')
-rw-r--r-- | src/dotty/tools/dotc/typer/Inferencing.scala | 38 |
1 files changed, 32 insertions, 6 deletions
diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala index c60f4c1f2..7c61f8c23 100644 --- a/src/dotty/tools/dotc/typer/Inferencing.scala +++ b/src/dotty/tools/dotc/typer/Inferencing.scala @@ -17,6 +17,7 @@ import Decorators._ import Uniques._ import config.Printers._ import annotation.tailrec +import reporting._ import collection.mutable object Inferencing { @@ -222,13 +223,38 @@ object Inferencing { val vs = variances(tp, qualifies) var changed = false - vs foreachBinding { (tvar, v) => - if (v != 0) { - typr.println(s"interpolate ${if (v == 1) "co" else "contra"}variant ${tvar.show} in ${tp.show}") - tvar.instantiate(fromBelow = v == 1) - changed = true - } + val hasUnreportedErrors = ctx.typerState.reporter match { + case r: StoreReporter if r.hasErrors => true + case _ => false } + // Avoid interpolating variables if typerstate has unreported errors. + // Reason: The errors might reflect unsatisfiable constraints. In that + // case interpolating without taking account the constraints risks producing + // nonsensical types that then in turn produce incomprehensible errors. + // An example is in neg/i1240.scala. Without the condition in the next code line + // we get for + // + // val y: List[List[String]] = List(List(1)) + // + // i1430.scala:5: error: type mismatch: + // found : Int(1) + // required: Nothing + // val y: List[List[String]] = List(List(1)) + // ^ + // With the condition, we get the much more sensical: + // + // i1430.scala:5: error: type mismatch: + // found : Int(1) + // required: String + // val y: List[List[String]] = List(List(1)) + if (!hasUnreportedErrors) + vs foreachBinding { (tvar, v) => + if (v != 0) { + typr.println(s"interpolate ${if (v == 1) "co" else "contra"}variant ${tvar.show} in ${tp.show}") + tvar.instantiate(fromBelow = v == 1) + changed = true + } + } if (changed) // instantiations might have uncovered new typevars to interpolate interpolateUndetVars(tree, ownedBy) else |