summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2014-12-15 16:21:26 +1000
committerAdriaan Moors <adriaan.moors@typesafe.com>2015-02-02 15:25:41 -0800
commit1970a8315ed3b2ff8877dfef2afcee936d59871b (patch)
tree0519d7b80607af264c1f3afda59b2e1c4d772219
parent5d7098c629bbb7cc0ab7e74c235bd4afca3de24e (diff)
downloadscala-1970a8315ed3b2ff8877dfef2afcee936d59871b.tar.gz
scala-1970a8315ed3b2ff8877dfef2afcee936d59871b.tar.bz2
scala-1970a8315ed3b2ff8877dfef2afcee936d59871b.zip
SI-9041 Avoid unreported type error with overloading, implicits
If `qual.foo(args)` fails to typecheck, we fall back to `ImplicitView(qual).foo(args)`. However, if the original type error stemmed from an overload ambiguity, the tree `Select(qual, 'foo')` holds onto an error symbol. The fall back attempt just returns an `Apply` tree containing the erroneous qualifier, as it does not want to issue cascading type errors. This commit replaces the error symbol with a `NoSymbol`, which triggers the second try typechecking to perform overload resolution again. A more principled fix might be to more pervasively duplicate trees before mutating their types and symbols, that this is beyond the scope of this bug fix.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala10
-rw-r--r--test/files/neg/t9041.check4
-rw-r--r--test/files/neg/t9041.scala17
3 files changed, 31 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index e6fa9a0142..fb47f45bc7 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -825,6 +825,16 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}
orElse { _ =>
val resetTree = resetAttrs(original)
+ resetTree match {
+ case treeInfo.Applied(fun, targs, args) =>
+ if (fun.symbol != null && fun.symbol.isError)
+ // SI-9041 Without this, we leak error symbols past the typer!
+ // because the fallback typechecking notices the error-symbol,
+ // refuses to re-attempt typechecking, and presumes that someone
+ // else was responsible for issuing the related type error!
+ fun.setSymbol(NoSymbol)
+ case _ =>
+ }
debuglog(s"fallback on implicits: ${tree}/$resetTree")
val tree1 = typed(resetTree, mode)
// Q: `typed` already calls `pluginsTyped` and `adapt`. the only difference here is that
diff --git a/test/files/neg/t9041.check b/test/files/neg/t9041.check
new file mode 100644
index 0000000000..669e9434e0
--- /dev/null
+++ b/test/files/neg/t9041.check
@@ -0,0 +1,4 @@
+t9041.scala:11: error: could not find implicit value for parameter cellSetter: CellSetter[scala.math.BigDecimal]
+ def setCell(cell: Cell, data: math.BigDecimal) { cell.setCellValue(data) }
+ ^
+one error found
diff --git a/test/files/neg/t9041.scala b/test/files/neg/t9041.scala
new file mode 100644
index 0000000000..2bdef0d3ae
--- /dev/null
+++ b/test/files/neg/t9041.scala
@@ -0,0 +1,17 @@
+// False negative test, requires overloading in Cell.
+
+trait Cell { def setCellValue(i: Int) = () ; def setCellValue(d: Double) = () }
+
+trait Nope {
+ def f = {
+ trait CellSetter[A] {
+ def setCell(cell: Cell, data: A): Unit
+ }
+ implicit val bigDecimalCellSetter = new CellSetter[math.BigDecimal]() {
+ def setCell(cell: Cell, data: math.BigDecimal) { cell.setCellValue(data) }
+ }
+ implicit class RichCell(cell: Cell) {
+ def setCellValue[A](data: A)(implicit cellSetter: CellSetter[A]) = cellSetter.setCell(cell, data)
+ }
+ }
+}