diff options
author | Paul Phillips <paulp@improving.org> | 2013-08-17 09:58:14 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-08-17 10:58:14 -0700 |
commit | 8f05647ca53da781b420be0723faf1cdbf14b2ff (patch) | |
tree | ceedf538752abb1fec532073ea7cc8b88388b4c9 /test | |
parent | b895541396015e5e50749b3f2fdb7fc4ab230919 (diff) | |
download | scala-8f05647ca53da781b420be0723faf1cdbf14b2ff.tar.gz scala-8f05647ca53da781b420be0723faf1cdbf14b2ff.tar.bz2 scala-8f05647ca53da781b420be0723faf1cdbf14b2ff.zip |
Pattern matcher: extractors become name-based.
An extractor is no longer required to return Option[T], and
can instead return anything which directly contains methods
with these signatures:
def isEmpty: Boolean
def get: T
If the type of get contains methods with the names of
product selectors (_1, _2, etc.) then the type and arity
of the extraction is inferred from the type of get. If
it does not contain _1, then it is a single value
extractor analogous like Option[T].
This has significant benefits and opens new territory:
- an AnyVal based Option-like class can be used which
leverages null as None, and no allocations are necessary
- for primitive types the benefit is squared (see below)
- the performance difference between case classes and
extractors should now be largely eliminated
- this in turn allows us to recapture great swaths of
memory which are currently squandered (e.g. every
TypeRef has fields for pre and args, even though these
are more than half the time NoPrefix and Nil)
Here is a primitive example:
final class OptInt(val x: Int) extends AnyVal {
def get: Int = x
def isEmpty = x == Int.MinValue // or whatever is appropriate
}
// This boxes TWICE: Int => Integer => Some(Integer)
def unapply(x: Int): Option[Int]
// This boxes NONCE
def unapply(x: Int): OptInt
As a multi-value example, after I contribute some methods to TypeRef:
def isEmpty = false
def get = this
def _1 = pre
def _2 = sym
def _3 = args
Then it's extractor becomes
def unapply(x: TypeRef) = x
Which, it need hardly be said, involves no allocations.
Diffstat (limited to 'test')
-rw-r--r-- | test/files/neg/t4425.check | 10 | ||||
-rw-r--r-- | test/files/neg/t4425.scala | 10 | ||||
-rw-r--r-- | test/files/neg/t4425b.check | 36 | ||||
-rw-r--r-- | test/files/neg/t6675.check | 2 | ||||
-rw-r--r-- | test/files/neg/t997.check | 7 | ||||
-rw-r--r-- | test/files/pos/annotated-treecopy/Impls_Macros_1.scala | 2 | ||||
-rw-r--r-- | test/files/run/matchonseq.scala | 10 | ||||
-rw-r--r-- | test/files/run/t7214.scala | 2 |
8 files changed, 53 insertions, 26 deletions
diff --git a/test/files/neg/t4425.check b/test/files/neg/t4425.check index cb5da6e7dc..95b88a6b3d 100644 --- a/test/files/neg/t4425.check +++ b/test/files/neg/t4425.check @@ -2,4 +2,12 @@ t4425.scala:3: error: object X is not a case class constructor, nor does it have 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 +t4425.scala:8: error: object X is not a case class constructor, nor does it have an unapply/unapplySeq method +Note: def unapply(x: Int)(y: Int): Some[(Int, Int)] exists in object X, but it cannot be used as an extractor due to its second non-implicit parameter list + 42 match { case _ X _ => () } + ^ +t4425.scala:13: error: object X is not a case class constructor, nor does it have an unapply/unapplySeq method +Note: def unapply(x: String)(y: String): Some[(Int, Int)] exists in object X, but it cannot be used as an extractor due to its second non-implicit parameter list + "" match { case _ X _ => () } + ^ +three errors found diff --git a/test/files/neg/t4425.scala b/test/files/neg/t4425.scala index d8cc6922f7..1714955c27 100644 --- a/test/files/neg/t4425.scala +++ b/test/files/neg/t4425.scala @@ -2,3 +2,13 @@ object Foo { object X { def unapply(x : Int)(y : Option[Int] = None) = None } 42 match { case _ X _ => () } } + +object Foo2 { + object X { def unapply(x : Int)(y: Int) = Some((2,2)) } + 42 match { case _ X _ => () } +} + +object Foo3 { + object X { def unapply(x : String)(y: String) = Some((2,2)) } + "" match { case _ X _ => () } +}
\ No newline at end of file diff --git a/test/files/neg/t4425b.check b/test/files/neg/t4425b.check index e43c489586..3af3027da1 100644 --- a/test/files/neg/t4425b.check +++ b/test/files/neg/t4425b.check @@ -22,34 +22,40 @@ t4425b.scala:10: error: object X is not a case class constructor, nor does it ha 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 +t4425b.scala:18: error: wrong number of patterns for object X offering <notype>: expected 1, found 2 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 +t4425b.scala:19: error: wrong number of patterns for object X offering <notype>: expected 1, found 2 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 +t4425b.scala:22: error: wrong number of patterns for object X offering <notype>: expected 1, found 2 + println( "" match { case X(_, _) => "ok" ; case _ => "fail" }) + ^ +t4425b.scala:22: error: wrong number of patterns for object X offering <notype>: expected 1, found 2 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 +t4425b.scala:23: error: wrong number of patterns for object X offering <notype>: expected 1, found 2 + println((X: Any) match { case X(_, _) => "ok" ; case _ => "fail" }) + ^ +t4425b.scala:23: error: wrong number of patterns for object X offering <notype>: expected 1, found 2 println((X: Any) match { case X(_, _) => "ok" ; case _ => "fail" }) ^ -t4425b.scala:31: error: wrong number of arguments for object X +t4425b.scala:31: error: wrong number of patterns for object X offering Nothing: expected 1, found 2 println( "" match { case _ X _ => "ok" ; case _ => "fail" }) ^ -t4425b.scala:32: error: wrong number of arguments for object X +t4425b.scala:32: error: wrong number of patterns for object X offering Nothing: expected 1, found 2 println((X: Any) match { case _ X _ => "ok" ; case _ => "fail" }) ^ -t4425b.scala:35: error: wrong number of arguments for object X +t4425b.scala:35: error: wrong number of patterns for object X offering Nothing: expected 1, found 2 + println( "" match { case X(_, _) => "ok" ; case _ => "fail" }) + ^ +t4425b.scala:35: error: wrong number of patterns for object X offering Nothing: expected 1, found 2 println( "" match { case X(_, _) => "ok" ; case _ => "fail" }) ^ -t4425b.scala:36: error: wrong number of arguments for object X +t4425b.scala:36: error: wrong number of patterns for object X offering Nothing: expected 1, found 2 + println((X: Any) match { case X(_, _) => "ok" ; case _ => "fail" }) + ^ +t4425b.scala:36: error: wrong number of patterns for object X offering Nothing: expected 1, found 2 println((X: Any) match { case X(_, _) => "ok" ; case _ => "fail" }) ^ -16 errors found +18 errors found diff --git a/test/files/neg/t6675.check b/test/files/neg/t6675.check index 3a277af866..aecf04cb68 100644 --- a/test/files/neg/t6675.check +++ b/test/files/neg/t6675.check @@ -1,4 +1,4 @@ -t6675.scala:10: warning: extractor pattern binds a single value to a Product3 of type (Int, Int, Int) +t6675.scala:10: warning: object X expects 3 patterns to hold (Int, Int, Int) but crushing into 3-tuple to fit single pattern (SI-6675) "" match { case X(b) => b } // should warn under -Xlint. Not an error because of SI-6111 ^ error: No warnings can be incurred under -Xfatal-warnings. diff --git a/test/files/neg/t997.check b/test/files/neg/t997.check index 186095f44a..be1e92c369 100644 --- a/test/files/neg/t997.check +++ b/test/files/neg/t997.check @@ -1,7 +1,10 @@ -t997.scala:13: error: wrong number of arguments for object Foo +t997.scala:13: error: wrong number of patterns for object Foo offering (String, String): expected 2, found 3 +"x" match { case Foo(a, b, c) => Console.println((a,b,c)) } + ^ +t997.scala:13: error: wrong number of patterns for object Foo offering (String, String): expected 2, found 3 "x" match { case Foo(a, b, c) => Console.println((a,b,c)) } ^ t997.scala:13: error: not found: value a "x" match { case Foo(a, b, c) => Console.println((a,b,c)) } ^ -two errors found +three errors found diff --git a/test/files/pos/annotated-treecopy/Impls_Macros_1.scala b/test/files/pos/annotated-treecopy/Impls_Macros_1.scala index cf58bc3dfd..ecf8916c46 100644 --- a/test/files/pos/annotated-treecopy/Impls_Macros_1.scala +++ b/test/files/pos/annotated-treecopy/Impls_Macros_1.scala @@ -22,7 +22,7 @@ object Macros { var b1 = new Transformer { override def transform(tree: Tree): Tree = tree match { case Ident(x) if (x==n) => Ident(TermName("_arg")) - case tt @ TypeTree() if tt.original != null => TypeTree(tt.tpe) setOriginal transform(tt.original) + case tt: TypeTree if tt.original != null => TypeTree(tt.tpe) setOriginal transform(tt.original) // without the fix to LazyTreeCopier.Annotated, we would need to uncomment the line below to make the macro work // that's because the pattern match in the input expression gets expanded into Typed(<x>, TypeTree(<Int @unchecked>)) // with the original of the TypeTree being Annotated(<@unchecked>, Ident(<x>)) diff --git a/test/files/run/matchonseq.scala b/test/files/run/matchonseq.scala index 49b406a6ec..f6f320245a 100644 --- a/test/files/run/matchonseq.scala +++ b/test/files/run/matchonseq.scala @@ -1,8 +1,8 @@ -object Test extends App{ - Vector(1,2,3) match { - case head +: tail => println("It worked! head=" + head) +object Test extends App { + Vector(1,2,3) match { + case head +: tail => println("It worked! head=" + head) } - Vector(1,2,3) match { - case init :+ last => println("It worked! last=" + last) + Vector(1,2,3) match { + case init :+ last => println("It worked! last=" + last) } } diff --git a/test/files/run/t7214.scala b/test/files/run/t7214.scala index ff1ea8082d..15c2c24fa0 100644 --- a/test/files/run/t7214.scala +++ b/test/files/run/t7214.scala @@ -25,7 +25,7 @@ class Crash { def unapply(a: Alias): Option[Any] = None } (t: Any) match { - case Extractor() => + case Extractor(_) => case _ => } |