import scala.language.{ postfixOps } object Test { def main(args: Array[String]) { ApplyFromJcl.run() Bug1093.run() Bug1094.run() Bug1270.run() Bug1281.run() Bug457.run() Bug508.run() Bug789.run() Bug881.run() Bug995.run() ClassDefInGuard.run() SeqUnapply.run() SimpleUnapply.run() Test1163_Order.run() Test717.run() Test903.run() TestEqualsPatternOpt.run() TestGuards.run() TestSequence01.run() TestSequence02.run() TestSequence03.run() TestSequence04.run() TestSequence05.run() TestSequence06.run() TestSequence07.run() TestSequence08.run() TestSimpleIntSwitch.run() TestStream.run() TestUnbox.run() Ticket11.run() Ticket2.run() Ticket346.run() Ticket37.run() Ticket44.run() } def assertEquals(a: Any, b: Any) { assert(a == b) } def assertEquals(msg: String, a: Any, b: Any) { assert(a == b, msg) } object SimpleUnapply { def run() { // from sortedmap, old version List((1, 2)).head match { case kv@(key, _) => kv.toString + " " + key.toString } } } object SeqUnapply { case class SFB(i: Int, xs: List[Int]) def run() { List(1, 2) match { case List(1) => assert(false, "wrong case") case List(1, 2, xs@_*) => assert(xs.isEmpty, "not empty") case Nil => assert(false, "wrong case") } SFB(1, List(1)) match { case SFB(_, List(x)) => assert(x == 1) case SFB(_, _) => assert(false) } } } object ApplyFromJcl { def run() { val p = (1, 2) Some(2) match { case Some(p._2) => case _ => assert(false) } } } object TestSimpleIntSwitch { def run() { assertEquals("s1", 1, 1 match { case 3 => 3 case 2 => 2 case 1 => 1 case 0 => 0 }) assertEquals("s2", 1, 1 match { case 1 => 1 case _ => 0 }) assertEquals("s2boxed", 1, (1: Any) match { case 1 => 1 case _ => 0 }) assertEquals("s3", 1, ("hello") match { case s: String => 1 //case _ => 0 // unreachable! }) val xyz: (Int, String, Boolean) = (1, "abc", true); assertEquals("s4", 1, xyz._1 match { case 1 => 1 case _ => 0 }) } } // #717 test path of case classes object Test717 { class Foo(j: Int) { case class Bar(i: Int) } val foo1 = new Foo(1) val foo2 = new Foo(2) def run() { val res = (foo1.Bar(2): Any) match { case foo1.Bar(2) => true } assert(res) } } /// trait Treez { self: Shmeez => abstract class Tree case class Beez(i: Int) extends Tree case object HagbardCeline extends Tree } trait Shmeez extends AnyRef with Treez { val tree: Tree def foo = tree match { case Beez(2) => 1 case HagbardCeline => 0 } } // multiple guards for same pattern object TestGuards extends Shmeez { val tree: Tree = Beez(2) def run() { val res = tree match { case Beez(x) if x == 3 => false case Beez(x) if x == 2 => true } assert(res) val ret = (Beez(3): Tree) match { case Beez(x) if x == 3 => true case Beez(x) if x == 2 => false } assert(ret) } } // test EqualsPatternClass in combination with MixTypes opt, bug #1276 object TestEqualsPatternOpt { val NoContext = new Object def run() { assertEquals(1, ((NoContext: Any) match { case that: AnyRef if this eq that => 0 case NoContext => 1 case _ => 2 })) } } // all ignoring patterns on List object TestSequence01 { def doMatch(xs: List[String]): String = xs match { case List(_*) => "ok" } def doMatch2(xs: List[String]): List[String] = xs match { case List(_, rest@_*) => rest.toList } def run() { val list1 = List() assertEquals(doMatch(list1), "ok") val list2 = List("1", "2", "3") assertEquals(doMatch(list2), "ok") val list3 = List("1", "2", "3") assertEquals(doMatch2(list3), List("2", "3")) } } // all ignoring patterns on Seq object TestSequence02 { def doMatch(l: Seq[String]): String = l match { case Seq(_*) => "ok" } def run() { val list1 = List() assertEquals(doMatch(list1), "ok") val list2 = List("1", "2", "3") assertEquals(doMatch(list2), "ok") val array3 = Array[String]() assertEquals(doMatch(array3), "ok") val array4 = Array[String]("ga", "gu") assertEquals(doMatch(array4), "ok") } } // right-ignoring patterns on List, defaults object TestSequence03 { def doMatch(xs: List[String]): String = xs match { case List(_, _, _, _*) => "ok" case _ => "not ok" } def run() { val list1 = List() assertEquals(doMatch(list1), "not ok") val list2 = List("1", "2", "3") assertEquals(doMatch(list2), "ok") val list3 = List("1", "2", "3", "4") assertEquals(doMatch(list3), "ok") } } // all- and right-ignoring pattern on case class w/ seq param object TestSequence04 { case class Foo(i: Int, chars: Char*) def run() { val a = Foo(0, 'a') match { case Foo(i, c, chars@_*) => c case _ => null } assertEquals(a, 'a') val b = Foo(0, 'a') match { case Foo(i, chars@_*) => 'b' case _ => null } assertEquals(b, 'b') } } // sealed case class with ignoring seq patterns object TestSequence05 { sealed abstract class Con; case class Foo() extends Con case class Bar(xs: Con*) extends Con def run() { val res = (Bar(Foo()): Con) match { case Bar(xs@_*) => xs // this should be optimized away to a pattern Bar(xs) case _ => Nil } assertEquals("res instance" + res.isInstanceOf[Seq[Con] forSome { type Con }] + " res(0)=" + res(0), true, res.isInstanceOf[Seq[Foo] forSome { type Foo }] && res(0) == Foo()) } } // (not regular) fancy guards / bug#644 object TestSequence06 { case class A(i: Any) def doMatch(x: Any, bla: Int) = x match { case x: A if (bla == 1) => 0 case A(1) => 1 case A(A(1)) => 2 } def run() { assertEquals(doMatch(A(null), 1), 0) assertEquals(doMatch(A(1), 2), 1) assertEquals(doMatch(A(A(1)), 2), 2) } } // List of chars object TestSequence07 { def doMatch1(xs: List[Char]) = xs match { case List(x, y, _*) => x :: y :: Nil } def doMatch2(xs: List[Char]) = xs match { case List(x, y, z, w) => List(z, w) } def doMatch3(xs: Seq[Char]) = xs match { case Seq(x, y, 'c', w@_*) => x :: y :: Nil case Seq(x, y, z@_*) => z } def doMatch4(xs: Seq[Char]) = xs match { case Seq(x, 'b') => x :: 'b' :: Nil case Seq(x, y, z@_*) => z.toList } def run() { assertEquals(List('a', 'b'), doMatch1(List('a', 'b', 'c', 'd'))) assertEquals(List('c', 'd'), doMatch2(List('a', 'b', 'c', 'd'))) assertEquals(List('a', 'b'), doMatch3(List('a', 'b', 'c', 'd'))) assertEquals(List('c', 'd'), doMatch4(List('a', 'b', 'c', 'd'))) } } // backquoted identifiers in pattern object TestSequence08 { def run() { val xs = List(2, 3) val ys = List(1, 2, 3) match { case x :: `xs` => xs case _ => Nil } assertEquals(xs, ys) } } // unapply for Streams object TestStream { def sum(stream: Stream[Int]): Int = stream match { case Stream.Empty => 0 case Stream.cons(hd, tl) => hd + sum(tl) } val str: Stream[Int] = List(1, 2, 3).iterator.toStream def run() { assertEquals(sum(str), 6) } } // bug#1163 order of temps must be preserved object Test1163_Order { abstract class Function case class Var(n: String) extends Function case class Const(v: Double) extends Function def f(): (Function, Function) = { (Var("x"): Function, Var("y"): Function) match { case (Const(v), Const(w)) => throw new Error case (leftOne, Var("z")) => throw new Error case (leftTwo, rightTwo) => (leftTwo, rightTwo) // was giving "y","x" } } def flips(l: List[Int]): Int = (l: @unchecked) match { case 1 :: ls => 0 case n :: ls => flips((l take n reverse) ::: (l drop n)) + 1 } def run() { assertEquals("both", (Var("x"), Var("y")), f) } } object TestUnbox { def run() { val xyz: (Int, String, Boolean) = (1, "abc", true) xyz._1 match { case 1 => "OK" case 2 => assert(false); "KO" case 3 => assert(false); "KO" } } } object Test903 { class Person(_name: String, _father: Person) { def name = _name def father = _father } object PersonFather { def unapply(p: Person): Option[Person] = if (p.father == null) None else Some(p.father) } def run() { val p1 = new Person("p1", null) val p2 = new Person("p2", p1) assertEquals((p2.name, p1.name), p2 match { case aPerson@PersonFather(f) => (aPerson.name, f.name) case _ => "No father" }) } } object Bug881 { object Foo1 { class Bar1(val x: String) def p(b: Bar1) = b.x def unapply(s: String): Option[Bar1] = Some(new Bar1(s)) } class Foo(j: Int) { case class Bar(i: Int) } def run() { "baz" match { case Foo1(x) => Foo1.p(x) } } } // these are exhaustive matches // should not generate any warnings def f[A](z: (Option[A], Option[A])) = z match { case (None, Some(x)) => 1 case (Some(x), None) => 2 case (Some(x), Some(y)) => 3 case _ => 4 } def g1[A](z: Option[List[A]]) = z match { case Some(Nil) => true case Some(x :: Nil) => true case _ => true } def g2[A](z: Option[List[A]]) = z match { case Some(x :: Nil) => true case Some(_) => false case _ => true } def h[A](x: (Option[A], Option[A])) = x match { case (None, _: Some[_]) => 1 case (_: Some[_], None) => 2 case (_: Some[_], _: Some[_]) => 3 case _ => 4 } def j = (List[Int](), List[Int](1)) match { case (Nil, _) => 'a' case (_, Nil) => 'b' case (h1 :: t1, h2 :: t2) => 'c' } def k(x: AnyRef) = x match { case null => 1 case _ => 2 } val FooBar = 42 def lala() = 42 match { case FooBar => true } object Bug1270 { // unapply13 class Sync { def apply(x: Int): Int = 42 def unapply(scrut: Any): Option[Int] = None } class Buffer { object Get extends Sync var ps: PartialFunction[Any, Any] = { case Get(y) if y > 4 => // y gets a wildcard type for some reason?! hack } } def run() { assert(!(new Buffer).ps.isDefinedAt(42)) } } object Bug1281 { class Sync { def unapplySeq(scrut: Int): Option[Seq[Int]] = { if (scrut == 42) Some(List(1, 2)) else None } } class Buffer { val Get = new Sync val jp: PartialFunction[Any, Any] = { case Get(xs) => // the argDummy should have proper arg.tpe (Int in this case) } } def run() { assert(!(new Buffer).jp.isDefinedAt(40)) assert(!(new Buffer).jp.isDefinedAt(42)) } } object ClassDefInGuard { val z: PartialFunction[Any, Any] = { case x :: xs if xs.forall { y => y.hashCode() > 0 } => 1 } def run() { val s: PartialFunction[Any, Any] = { case List(4 :: xs) => 1 case List(5 :: xs) => 1 case _ if false => case List(3 :: xs) if List(3: Any).forall { g => g.hashCode() > 0 } => 1 } z.isDefinedAt(42) s.isDefinedAt(42) // just load the thing, to see if the classes are found (None: Option[Boolean] @unchecked) match { case x if x.map(x => x).isEmpty => } } } // bug#457 object Bug457 { def method1() = { val x = "Hello, world"; val y = 100; y match { case _: Int if (x match { case t => t.trim().length() > 0 }) => false; case _ => true; } } def method2(): scala.Boolean = { val x: String = "Hello, world"; val y: scala.Int = 100; { var temp1: scala.Int = y var result: scala.Boolean = false if ({ var result1: scala.Boolean = true; if (y == 100) result1 else throw new MatchError("crazybox.scala, line 11") } && (y > 90)) result else throw new MatchError("crazybox.scala, line 9") } } def run() { method1(); method2(); } } // bug#508 object Bug508 { case class Operator(x: Int); val EQ = new Operator(2); def analyze(x: Tuple2[Operator, Int]) = (x: @unchecked) match { case (EQ, 0) => "0" case (EQ, 1) => "1" case (EQ, 2) => "2" } def run() { val x = (EQ, 0); assertEquals("0", analyze(x)); // should print "0" val y = (EQ, 1); assertEquals("1", analyze(y)); // should print "1" val z = (EQ, 2); assertEquals("2", analyze(z)); // should print "2" } } // bug#789 object Bug789 { // don't do this at home trait Impl trait SizeImpl extends Impl { def size = 42 } trait ColorImpl extends Impl { def color = "red" } type Both = SizeImpl with ColorImpl def info(x: Impl) = x match { case x: Both => "size " + x.size + " color " + x.color // you wish case x: SizeImpl => "!size " + x.size case x: ColorImpl => "color " + x.color case _ => "n.a." } def info2(x: Impl) = x match { case x: SizeImpl with ColorImpl => "size " + x.size + " color " + x.color // you wish case x: SizeImpl => "!size " + x.size case x: ColorImpl => "color " + x.color case _ => "n.a." } def run() { // make up some class that has a size class MyNode extends SizeImpl assertEquals("!size 42", info(new MyNode)) assertEquals("!size 42", info2(new MyNode)) } } // bug#995 object Bug995 { def foo(v: Any): String = v match { case s: Seq[_] => "Seq" // see hack in object Seq.unapplySeq case a: AnyRef if runtime.ScalaRunTime.isArray(a) => "Array" case _ => v.toString } def run() { assertEquals("Array", foo(Array(0))) } } // bug#1093 (contribution #460) object Bug1093 { def run() { assert((Some(3): @unchecked) match { case Some(1 | 2) => false case Some(3) => true }) } } // bug#1094 (contribution #461) object Bug1094 { def foo(ps: String*) = "Foo" case class X(p: String, ps: String*) def bar = X("a", "b") match { case X(p, ps@_*) => foo(ps: _*) } def run() { assertEquals("Foo", bar) } } // #2 class Outer_2 { case class Foo(x: Int, y: Int) { override def equals(other: Any) = other match { case Outer_2.this.Foo(`x`, `y`) => true case _ => false } } } object Ticket2 { def run() { val o1 = new Outer_2; val o2 = new Outer_2; val x: Any = o1.Foo(1, 2); val y: Any = o2.Foo(1, 2) assert(x != y, "equals test returns true (but should not)") assert(x match { case o2.Foo(x, y) => false case o1.Foo(x, y) => true case _ => false }, "match enters wrong case") } } // #11 class MyException1 extends Exception // Commenting out the following line and uncommenting the second line // will cause the test to succeed. trait SpecialException extends MyException1 // trait SpecialException class MyException2 extends MyException1 with SpecialException object Ticket11 { def run() { Array[Throwable](new Exception("abc"), new MyException1, new MyException2).foreach { e => try { throw e } catch { case e: SpecialException => { assume(e.isInstanceOf[SpecialException]) } case e => { assume(e.isInstanceOf[Throwable]) } } } } } // #37 object Ticket37 { def foo() {} val (a, b) = { foo(); (2, 3) } def run() { assertEquals(this.a, 2) } } // #44 trait _X { case class _Foo(); object _Bar { def unapply(foo: _Foo): Boolean = true; } } object Y extends _X { val foo = _Foo() foo match { case _Bar() => case _ => assert(false) } } object Ticket44 { def run() { assert(Y.toString ne null) /*instantiate Y*/ } } object Ticket211 { def run() { (Some(123): Option[Int]) match { case (x: Option[a]) if false => {}; case (y: Option[b]) => {}; } } } // this test case checks nothing more than whether // case N for object N is translated to a check scrutinee.equals(N) // (or the other way round)... for a long time, we got away with // scrutinee eq N, but those golden days are, apparently, over. object Ticket346 { class L(val content: List[Int]) { def isEmpty = content.isEmpty def head = content.head def tail = content.tail override def equals(that: Any): Boolean = { val result = that.isInstanceOf[N.type] println("L(" + content + ").equals(" + that + ") returning " + result) result } } object N extends L(Nil) { override def equals(that: Any): Boolean = (that.isInstanceOf[L] && that.asInstanceOf[L].isEmpty) } object C { def unapply(xs: L): Option[(Int, L)] = { if (xs.isEmpty) { println("xs is empty"); None } else Some((xs.head, new L(xs.tail))) } } def empty(xs: L): Boolean = xs match { case N => true case _ => false } def singleton(xs: L): Boolean = xs match { case C(_, N) => true case _ => false } def run() { assert(empty(new L(Nil))) assert(singleton(new L(List(1)))) } } // end Ticket346 }