From f1e553ecfbea25bcc7e13294f6104d599336f460 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 29 Aug 2015 21:42:29 +1000 Subject: SI-9029 Fix regression in extractor patterns The unified treatment of classical and named-based pattern matching does not correctly handle the generalization of "tuple capture". By "tuple capture", I mean: ``` scala> object Extractor { def unapply(a: Any): Option[(Int, String)] = Some((1, "2")) } defined object Extractor scala> "" match { case Extractor(x: Int, y: String) => } scala> "" match { case Extractor(xy : (Int, String)) => } warning: there was one deprecation warning; re-run with -deprecation for details scala> :warnings :9: warning: object Extractor expects 2 patterns to hold (Int, String) but crushing into 2-tuple to fit single pattern (SI-6675) "" match { case Extractor(xy : (Int, String)) => } ^ ``` Name based pattern matching, new in Scala 2.11, allows one to deconstruct the elements that structurally resembles `ProductN`: ``` scala> class P2(val _1: Int, val _2: String) defined class P2 scala> object Extractor { def unapply(a: Any): Option[P2] = Some(new P2(1, "2")) } defined object Extractor scala> "" match { case Extractor(x: Int, y: String) => } ``` However, attempting to extract the `P2` in its entirety leads to an internal error: ``` scala> "" match { case Extractor(p2: P2) => } :10: warning: fruitless type test: a value of type (Int, String) cannot also be a P2 "" match { case Extractor(p2: P2) => } ^ :10: error: error during expansion of this match (this is a scalac bug). The underlying error was: type mismatch; found : P2 required: (Int, String) "" match { case Extractor(p2: P2) => } ^ ``` Note that this match was legal and warning free in 2.10. This commit avoids the hard-coded assumption that the "tuple capture" results in a `TupleN`, and instead keeps track of the product-ish type from which we extracted the element types. I have also opted not to limit the deprecation warning to `TupleN` extractors. --- test/files/run/t9029.scala | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 test/files/run/t9029.scala (limited to 'test/files/run/t9029.scala') diff --git a/test/files/run/t9029.scala b/test/files/run/t9029.scala new file mode 100644 index 0000000000..c01033b76e --- /dev/null +++ b/test/files/run/t9029.scala @@ -0,0 +1,15 @@ +class Y(val _2: Int, val _1: String) + +object X { def unapply(u: Unit): Option[Y] = Some(new Y(42, "!")) } + +object Test { + def test1 = { + val X(y) = () + val yy: Y = y + assert(yy._1 == "!") + assert(yy._2 == 42) + } + def main(args: Array[String]): Unit = { + test1 + } +} -- cgit v1.2.3