summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala7
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Unapplies.scala10
-rw-r--r--test/files/neg/t4425.check3
-rw-r--r--test/files/neg/t4425b.check55
-rw-r--r--test/files/neg/t4425b.scala38
5 files changed, 109 insertions, 4 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index 81f5545695..7f4bf0dfbc 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -593,7 +593,12 @@ trait ContextErrors {
}
def CaseClassConstructorError(tree: Tree) = {
- issueNormalTypeError(tree, tree.symbol + " is not a case class constructor, nor does it have an unapply/unapplySeq method")
+ val baseMessage = tree.symbol + " is not a case class constructor, nor does it have an unapply/unapplySeq method"
+ val addendum = directUnapplyMember(tree.symbol.info) match {
+ case sym if hasMultipleNonImplicitParamLists(sym) => s"\nNote: ${sym.defString} exists in ${tree.symbol}, but it cannot be used as an extractor due to its second non-implicit parameter list"
+ case _ => ""
+ }
+ issueNormalTypeError(tree, baseMessage + addendum)
setError(tree)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
index 0e2c836860..18b8f8a9ce 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
@@ -46,8 +46,14 @@ trait Unapplies extends ast.TreeDSL {
}
}
- /** returns unapply or unapplySeq if available */
- def unapplyMember(tp: Type): Symbol = (tp member nme.unapply) orElse (tp member nme.unapplySeq)
+ /** Returns unapply or unapplySeq if available, without further checks.
+ */
+ def directUnapplyMember(tp: Type): Symbol = (tp member nme.unapply) orElse (tp member nme.unapplySeq)
+
+ /** Filters out unapplies with multiple (non-implicit) parameter lists,
+ * as they cannot be used as extractors
+ */
+ def unapplyMember(tp: Type): Symbol = directUnapplyMember(tp) filter (sym => !hasMultipleNonImplicitParamLists(sym))
object ExtractorType {
def unapply(tp: Type): Option[Symbol] = unapplyMember(tp).toOption
diff --git a/test/files/neg/t4425.check b/test/files/neg/t4425.check
index 0f2fe6f2d1..cb5da6e7dc 100644
--- a/test/files/neg/t4425.check
+++ b/test/files/neg/t4425.check
@@ -1,4 +1,5 @@
-t4425.scala:3: error: isInstanceOf cannot test if value types are references.
+t4425.scala:3: error: object X is not a case class constructor, nor does it have an unapply/unapplySeq method
+Note: def unapply(x: Int)(y: Option[Int]): None.type exists in object X, but it cannot be used as an extractor due to its second non-implicit parameter list
42 match { case _ X _ => () }
^
one error found
diff --git a/test/files/neg/t4425b.check b/test/files/neg/t4425b.check
new file mode 100644
index 0000000000..e43c489586
--- /dev/null
+++ b/test/files/neg/t4425b.check
@@ -0,0 +1,55 @@
+t4425b.scala:5: error: object X is not a case class constructor, nor does it have an unapply/unapplySeq method
+Note: def unapply(x: String)(y: String): Nothing exists in object X, but it cannot be used as an extractor due to its second non-implicit parameter list
+ println( "" match { case _ X _ => "ok" ; case _ => "fail" })
+ ^
+t4425b.scala:6: error: object X is not a case class constructor, nor does it have an unapply/unapplySeq method
+Note: def unapply(x: String)(y: String): Nothing exists in object X, but it cannot be used as an extractor due to its second non-implicit parameter list
+ println((X: Any) match { case _ X _ => "ok" ; case _ => "fail" })
+ ^
+t4425b.scala:7: error: object X is not a case class constructor, nor does it have an unapply/unapplySeq method
+Note: def unapply(x: String)(y: String): Nothing exists in object X, but it cannot be used as an extractor due to its second non-implicit parameter list
+ println( "" match { case X(_) => "ok" ; case _ => "fail" })
+ ^
+t4425b.scala:8: error: object X is not a case class constructor, nor does it have an unapply/unapplySeq method
+Note: def unapply(x: String)(y: String): Nothing exists in object X, but it cannot be used as an extractor due to its second non-implicit parameter list
+ println((X: Any) match { case X(_) => "ok" ; case _ => "fail" })
+ ^
+t4425b.scala:9: error: object X is not a case class constructor, nor does it have an unapply/unapplySeq method
+Note: def unapply(x: String)(y: String): Nothing exists in object X, but it cannot be used as an extractor due to its second non-implicit parameter list
+ println( "" match { case X(_, _) => "ok" ; case _ => "fail" })
+ ^
+t4425b.scala:10: error: object X is not a case class constructor, nor does it have an unapply/unapplySeq method
+Note: def unapply(x: String)(y: String): Nothing exists in object X, but it cannot be used as an extractor due to its second non-implicit parameter list
+ println((X: Any) match { case X(_, _) => "ok" ; case _ => "fail" })
+ ^
+t4425b.scala:18: error: result type Nothing of unapply defined in method unapply in object X does not conform to Option[_] or Boolean
+ println( "" match { case _ X _ => "ok" ; case _ => "fail" })
+ ^
+t4425b.scala:19: error: result type Nothing of unapply defined in method unapply in object X does not conform to Option[_] or Boolean
+ println((X: Any) match { case _ X _ => "ok" ; case _ => "fail" })
+ ^
+t4425b.scala:20: error: result type Nothing of unapply defined in method unapply in object X does not conform to Option[_] or Boolean
+ println( "" match { case X(_) => "ok" ; case _ => "fail" })
+ ^
+t4425b.scala:21: error: result type Nothing of unapply defined in method unapply in object X does not conform to Option[_] or Boolean
+ println((X: Any) match { case X(_) => "ok" ; case _ => "fail" })
+ ^
+t4425b.scala:22: error: result type Nothing of unapply defined in method unapply in object X does not conform to Option[_] or Boolean
+ println( "" match { case X(_, _) => "ok" ; case _ => "fail" })
+ ^
+t4425b.scala:23: error: result type Nothing of unapply defined in method unapply in object X does not conform to Option[_] or Boolean
+ println((X: Any) match { case X(_, _) => "ok" ; case _ => "fail" })
+ ^
+t4425b.scala:31: error: wrong number of arguments for object X
+ println( "" match { case _ X _ => "ok" ; case _ => "fail" })
+ ^
+t4425b.scala:32: error: wrong number of arguments for object X
+ println((X: Any) match { case _ X _ => "ok" ; case _ => "fail" })
+ ^
+t4425b.scala:35: error: wrong number of arguments for object X
+ println( "" match { case X(_, _) => "ok" ; case _ => "fail" })
+ ^
+t4425b.scala:36: error: wrong number of arguments for object X
+ println((X: Any) match { case X(_, _) => "ok" ; case _ => "fail" })
+ ^
+16 errors found
diff --git a/test/files/neg/t4425b.scala b/test/files/neg/t4425b.scala
new file mode 100644
index 0000000000..861e9521f6
--- /dev/null
+++ b/test/files/neg/t4425b.scala
@@ -0,0 +1,38 @@
+object Test1 {
+ object X { def unapply(x : String)(y: String) = throw new Exception }
+
+ def f1() {
+ println( "" match { case _ X _ => "ok" ; case _ => "fail" })
+ println((X: Any) match { case _ X _ => "ok" ; case _ => "fail" })
+ println( "" match { case X(_) => "ok" ; case _ => "fail" })
+ println((X: Any) match { case X(_) => "ok" ; case _ => "fail" })
+ println( "" match { case X(_, _) => "ok" ; case _ => "fail" })
+ println((X: Any) match { case X(_, _) => "ok" ; case _ => "fail" })
+ }
+}
+
+object Test2 {
+ object X { def unapply(x : String) = throw new Exception }
+
+ def f1() {
+ println( "" match { case _ X _ => "ok" ; case _ => "fail" })
+ println((X: Any) match { case _ X _ => "ok" ; case _ => "fail" })
+ println( "" match { case X(_) => "ok" ; case _ => "fail" })
+ println((X: Any) match { case X(_) => "ok" ; case _ => "fail" })
+ println( "" match { case X(_, _) => "ok" ; case _ => "fail" })
+ println((X: Any) match { case X(_, _) => "ok" ; case _ => "fail" })
+ }
+}
+
+object Test3 {
+ object X { def unapply(x : String) = None }
+
+ def f1() {
+ println( "" match { case _ X _ => "ok" ; case _ => "fail" })
+ println((X: Any) match { case _ X _ => "ok" ; case _ => "fail" })
+ println( "" match { case X(_) => "ok" ; case _ => "fail" })
+ println((X: Any) match { case X(_) => "ok" ; case _ => "fail" })
+ println( "" match { case X(_, _) => "ok" ; case _ => "fail" })
+ println((X: Any) match { case X(_, _) => "ok" ; case _ => "fail" })
+ }
+}