Skip to content

Commit d2120ca

Browse files
committed
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.
1 parent a57b4a3 commit d2120ca

File tree

2 files changed

+40
-6
lines changed

2 files changed

+40
-6
lines changed

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

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import Decorators._
1717
import Uniques._
1818
import config.Printers._
1919
import annotation.tailrec
20+
import reporting._
2021
import collection.mutable
2122

2223
object Inferencing {
@@ -222,13 +223,38 @@ object Inferencing {
222223

223224
val vs = variances(tp, qualifies)
224225
var changed = false
225-
vs foreachBinding { (tvar, v) =>
226-
if (v != 0) {
227-
typr.println(s"interpolate ${if (v == 1) "co" else "contra"}variant ${tvar.show} in ${tp.show}")
228-
tvar.instantiate(fromBelow = v == 1)
229-
changed = true
230-
}
226+
val hasUnreportedErrors = ctx.typerState.reporter match {
227+
case r: StoreReporter if r.hasErrors => true
228+
case _ => false
231229
}
230+
// Avoid interpolating variables if typerstate has unreported errors.
231+
// Reason: The errors might reflect unsatisfiable constraints. In that
232+
// case interpolating without taking account the constraints risks producing
233+
// nonsensical types that then in turn produce incomprehensible errors.
234+
// An example is in neg/i1240.scala. Without the condition in the next code line
235+
// we get for
236+
//
237+
// val y: List[List[String]] = List(List(1))
238+
//
239+
// i1430.scala:5: error: type mismatch:
240+
// found : Int(1)
241+
// required: Nothing
242+
// val y: List[List[String]] = List(List(1))
243+
// ^
244+
// With the condition, we get the much more sensical:
245+
//
246+
// i1430.scala:5: error: type mismatch:
247+
// found : Int(1)
248+
// required: String
249+
// val y: List[List[String]] = List(List(1))
250+
if (!hasUnreportedErrors)
251+
vs foreachBinding { (tvar, v) =>
252+
if (v != 0) {
253+
typr.println(s"interpolate ${if (v == 1) "co" else "contra"}variant ${tvar.show} in ${tp.show}")
254+
tvar.instantiate(fromBelow = v == 1)
255+
changed = true
256+
}
257+
}
232258
if (changed) // instantiations might have uncovered new typevars to interpolate
233259
interpolateUndetVars(tree, ownedBy)
234260
else

tests/neg/i1430.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
object Test {
2+
3+
val x: List[String] = List(1) // error: found Int(1), expected: String
4+
5+
val y: List[List[String]] = List(List(1)) // error: found Int(1), expected: String
6+
7+
val z: (List[String], List[Int]) = (List(1), List("a")) // error: found Int(1), expected: String // error: found String(a), expected: Int
8+
}

0 commit comments

Comments
 (0)