summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2013-09-27 09:25:37 -0700
committerPaul Phillips <paulp@improving.org>2013-09-27 09:42:37 -0700
commit7fa77afa9322d4d31b132d1c1c8b57c7a3199348 (patch)
tree17bef811bee14d52333af56120a802d02a013948
parent1a3c16fd36407bb2308bbb84739601544ac4a2e5 (diff)
downloadscala-7fa77afa9322d4d31b132d1c1c8b57c7a3199348.tar.gz
scala-7fa77afa9322d4d31b132d1c1c8b57c7a3199348.tar.bz2
scala-7fa77afa9322d4d31b132d1c1c8b57c7a3199348.zip
SI-3971 error message carat mispoints at curried methods.
Point at the beginning of the first argument list when reporting an error, as this is most easily associated with the application taking place (which may involve multiple applies in succession.) Thanks to retronym for figuring out why issuing a better error message broke the compiler on non-erroneous compile runs. The changes to "treesInResult" are the consequence.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala12
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala3
-rw-r--r--test/files/neg/t3971.check21
-rw-r--r--test/files/neg/t3971.scala12
4 files changed, 47 insertions, 1 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index 1f4d5cbac2..f893e4f0ff 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -157,6 +157,16 @@ trait ContextErrors {
}
def AdaptTypeError(tree: Tree, found: Type, req: Type) = {
+ // SI-3971 unwrapping to the outermost Apply helps prevent confusion with the
+ // error message point.
+ def callee = {
+ def unwrap(t: Tree): Tree = t match {
+ case Apply(app: Apply, _) => unwrap(app)
+ case _ => t
+ }
+ unwrap(tree)
+ }
+
// If the expected type is a refinement type, and the found type is a refinement or an anon
// class, we can greatly improve the error message by retyping the tree to recover the actual
// members present, then display along with the expected members. This is done here because
@@ -181,7 +191,7 @@ trait ContextErrors {
}
assert(!foundType.isErroneous && !req.isErroneous, (foundType, req))
- issueNormalTypeError(tree, withAddendum(tree.pos)(typeErrorMsg(foundType, req)))
+ issueNormalTypeError(callee, withAddendum(callee.pos)(typeErrorMsg(foundType, req)))
infer.explainTypes(foundType, req)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 157c6ba4de..d88a615c7f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -4177,6 +4177,9 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
case If(_, t, e) => treesInResult(t) ++ treesInResult(e)
case Try(b, catches, _) => treesInResult(b) ++ catches
case Typed(r, Function(Nil, EmptyTree)) => treesInResult(r)
+ case Select(qual, name) => treesInResult(qual)
+ case Apply(fun, args) => treesInResult(fun) ++ args.flatMap(treesInResult)
+ case TypeApply(fun, args) => treesInResult(fun) ++ args.flatMap(treesInResult)
case _ => Nil
})
def errorInResult(tree: Tree) = treesInResult(tree) exists (_.pos == typeError.errPos)
diff --git a/test/files/neg/t3971.check b/test/files/neg/t3971.check
new file mode 100644
index 0000000000..8685119876
--- /dev/null
+++ b/test/files/neg/t3971.check
@@ -0,0 +1,21 @@
+t3971.scala:6: error: type mismatch;
+ found : Int
+ required: String
+ f(g("abc")("def")) // g returns Int, needs String
+ ^
+t3971.scala:7: error: type mismatch;
+ found : Int(5)
+ required: String
+ f(5)
+ ^
+t3971.scala:8: error: type mismatch;
+ found : Int
+ required: String
+ f(h("abc"))
+ ^
+t3971.scala:11: error: type mismatch;
+ found : Boolean
+ required: String
+ ({"ab".reverse; "ba".equals})(0): String
+ ^
+four errors found
diff --git a/test/files/neg/t3971.scala b/test/files/neg/t3971.scala
new file mode 100644
index 0000000000..35f64fde0c
--- /dev/null
+++ b/test/files/neg/t3971.scala
@@ -0,0 +1,12 @@
+class A {
+ def f(x: String) = x
+ def g(x: String)(y: String): Int = x.length + y.length
+ def h(x: String) = x.length
+
+ f(g("abc")("def")) // g returns Int, needs String
+ f(5)
+ f(h("abc"))
+
+ // a perverse piece of code from a perverse coder
+ ({"ab".reverse; "ba".equals})(0): String
+}