aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-08-01 14:37:57 +0200
committerMartin Odersky <odersky@gmail.com>2016-08-16 17:32:54 +0200
commitd2120ca8accb7d6b8438431931c84870e835512c (patch)
tree651c495bd7c92061500118c550eddb16422c7a52 /src
parenta57b4a3ec5b139711ad7e729040165e58751a49c (diff)
downloaddotty-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.scala38
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