summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-01-08 12:10:10 +0100
committerJason Zaugg <jzaugg@gmail.com>2013-01-08 12:26:41 +0100
commit7a23562431e3e9673112b0f5ec5624eb28194ee5 (patch)
treeb738cdde615dd723ff3e7e6a708cff0d4edcadde
parent1381cda86ddeca1b9829a9c53ff9372cfd816735 (diff)
downloadscala-7a23562431e3e9673112b0f5ec5624eb28194ee5.tar.gz
scala-7a23562431e3e9673112b0f5ec5624eb28194ee5.tar.bz2
scala-7a23562431e3e9673112b0f5ec5624eb28194ee5.zip
SI-6912 Avoid a typer cycle in overload resolution.
c800d1fe, and followup commits 1ddc9358 and b10b5821 modified error handling in `Infer#inferExprAlternative`. After these changes, this method could fail to resolve the overloaded alternative if: best != NoSymbol && !competing.isEmpty && !noAlternatives && pt.isErroneous This commit calls `setError` in that case, which prevents the cycle in `adapt`. While I didn't extract a reproduction from the original code base, I've included a test case that exhibits the same symptom. It was actually pretty tough to find an program that got close to this code path, but luckilly we've been pretty close to this bug in SI-5553 / 4f99c2e5, and those test cases formed the basis for this one.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala7
-rw-r--r--test/files/neg/t6912.check4
-rw-r--r--test/files/neg/t6912.scala9
3 files changed, 20 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 7ae8923e43..771b1255d3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -1510,6 +1510,13 @@ trait Infer extends Checkable {
} else if (!competing.isEmpty) {
if (noAlternatives) NoBestExprAlternativeError(tree, pt, isSecondTry)
else if (!pt.isErroneous) AmbiguousExprAlternativeError(tree, pre, best, competing.head, pt, isSecondTry)
+ else {
+ // SI-6912 Don't give up and leave an OverloadedType on the tree.
+ // Originally I wrote this as `if (secondTry) ... `, but `tryTwice` won't attempt the second try
+ // unless an error is issued. We're not issuing an error, in the assumption that it would be
+ // spurious in light of the erroneous expected type
+ setError(tree)
+ }
} else {
// val applicable = alts1 filter (alt =>
// global.typer.infer.isWeaklyCompatible(pre.memberType(alt), pt))
diff --git a/test/files/neg/t6912.check b/test/files/neg/t6912.check
new file mode 100644
index 0000000000..137b651705
--- /dev/null
+++ b/test/files/neg/t6912.check
@@ -0,0 +1,4 @@
+t6912.scala:8: error: not found: type Xxxx
+ def test[T]: Xxxx = Foo1[T]
+ ^
+one error found
diff --git a/test/files/neg/t6912.scala b/test/files/neg/t6912.scala
new file mode 100644
index 0000000000..f2540ee8c6
--- /dev/null
+++ b/test/files/neg/t6912.scala
@@ -0,0 +1,9 @@
+object Foo1 {
+ def apply[T](a: Int = 0): Nothing = sys.error("")
+ def apply[T](z: String = ""): Nothing = sys.error("")
+}
+
+object Test {
+ // Triggered a cycle in Typers#adapt
+ def test[T]: Xxxx = Foo1[T]
+}