summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala42
-rw-r--r--test/files/neg/abstract-class-2.check5
-rw-r--r--test/files/neg/abstract-class-2.scala14
-rw-r--r--test/files/neg/abstract-class-error.check5
-rw-r--r--test/files/neg/abstract-class-error/J.java4
-rw-r--r--test/files/neg/abstract-class-error/S.scala4
6 files changed, 74 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 3eb5107870..a23e5d704e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -507,6 +507,48 @@ abstract class RefChecks extends InfoTransform {
else analyzer.varNotice(member)
)
}
+ else if (underlying.isMethod) {
+ // If there is a concrete method whose name matches the unimplemented
+ // abstract method, and a cursory examination of the difference reveals
+ // something obvious to us, let's make it more obvious to them.
+ val abstractParams = underlying.tpe.paramTypes
+ val matchingName = clazz.tpe.nonPrivateMembersAdmitting(VBRIDGE)
+ val matchingArity = matchingName filter { m =>
+ !m.isDeferred &&
+ (m.name == underlying.name) &&
+ (m.tpe.paramTypes.size == underlying.tpe.paramTypes.size) &&
+ (m.tpe.typeParams.size == underlying.tpe.typeParams.size)
+ }
+
+ matchingArity match {
+ // So far so good: only one candidate method
+ case concrete :: Nil =>
+ val mismatches = abstractParams zip concrete.tpe.paramTypes filterNot { case (x, y) => x =:= y }
+ mismatches match {
+ // Only one mismatched parameter: say something useful.
+ case (pa, pc) :: Nil =>
+ val addendum =
+ if (pa.typeSymbol == pc.typeSymbol) {
+ // TODO: what is the optimal way to test for a raw type at this point?
+ // Compilation has already failed so we shouldn't have to worry overmuch
+ // about forcing types.
+ if (underlying.isJavaDefined && pa.typeArgs.isEmpty && pa.typeSymbol.typeParams.nonEmpty)
+ ". To implement a raw type, use %s[_]".format(pa)
+ else if (pa.prefix =:= pc.prefix)
+ ": their type parameters differ"
+ else
+ ": their prefixes (i.e. enclosing instances) differ"
+ }
+ else ""
+
+ undefined("\n(Note that %s does not match %s%s)".format(pa, pc, addendum))
+ case xs =>
+ undefined("")
+ }
+ case _ =>
+ undefined("")
+ }
+ }
else undefined("")
}
diff --git a/test/files/neg/abstract-class-2.check b/test/files/neg/abstract-class-2.check
new file mode 100644
index 0000000000..ca79dd8293
--- /dev/null
+++ b/test/files/neg/abstract-class-2.check
@@ -0,0 +1,5 @@
+abstract-class-2.scala:11: error: object creation impossible, since method f in trait S2 of type (x: P2.this.p.S1)Int is not defined
+(Note that P.this.p.S1 does not match P2.this.S1: their prefixes (i.e. enclosing instances) differ)
+ object O2 extends S2 {
+ ^
+one error found
diff --git a/test/files/neg/abstract-class-2.scala b/test/files/neg/abstract-class-2.scala
new file mode 100644
index 0000000000..19f74f3da6
--- /dev/null
+++ b/test/files/neg/abstract-class-2.scala
@@ -0,0 +1,14 @@
+class P {
+ trait S1
+ val p = new P
+
+ trait S2 {
+ def f(x: p.S1): Int
+ }
+}
+
+class P2 extends P {
+ object O2 extends S2 {
+ def f(x: S1) = 5
+ }
+}
diff --git a/test/files/neg/abstract-class-error.check b/test/files/neg/abstract-class-error.check
new file mode 100644
index 0000000000..b8a0c6e70b
--- /dev/null
+++ b/test/files/neg/abstract-class-error.check
@@ -0,0 +1,5 @@
+S.scala:1: error: class S needs to be abstract, since method g in class J of type (y: Int,z: java.util.List)Int is not defined
+(Note that java.util.List does not match java.util.List[String]. To implement a raw type, use java.util.List[_])
+class S extends J {
+ ^
+one error found
diff --git a/test/files/neg/abstract-class-error/J.java b/test/files/neg/abstract-class-error/J.java
new file mode 100644
index 0000000000..5877f5cc5b
--- /dev/null
+++ b/test/files/neg/abstract-class-error/J.java
@@ -0,0 +1,4 @@
+public abstract class J {
+ public abstract int f();
+ public abstract int g(int y, java.util.List z);
+} \ No newline at end of file
diff --git a/test/files/neg/abstract-class-error/S.scala b/test/files/neg/abstract-class-error/S.scala
new file mode 100644
index 0000000000..67f6d8593e
--- /dev/null
+++ b/test/files/neg/abstract-class-error/S.scala
@@ -0,0 +1,4 @@
+class S extends J {
+ def f() = 55
+ def g(y: Int, z: java.util.List[String]) = 11
+}