Aladdin - Scala Bugtracking
[#188] project: compiler priority: low category: bug
submitter assigned to status date submitted
Matthias Burak fixed 2003-10-07 11:11:32.0
subject Incorrect behavior of pattern matcher
code
case class One()
case class Two(x: Any)

object Main extends Object with Application {
  def test(xs: List[Any]) = xs match {
    case List(((Two(One()) | Two(Two(_))), One()) | (Two(_), Two(_))) =>
    	Console.println("case");
    case List(p) if !p.isInstanceOf[Tuple2[A,B] forSome { type A; type B }]=>
    	Console.println("broken test program, we want to test pairs here.");
    case _ =>
    	Console.println("default");
  }

  val p1 = (One(), One())
  test(List(p1));
  val p2 = (One(), Two(One()))
  test(List(p2));
  val p3 = (Two(One()), One());
  test(List(p3))
  val p4 = (Two(One()), Two(One()))
  test(List(p4));
}
what happened
Method foo's first case is supposed to match all Lists of length two whose first element is Two(*) \
and whose second element is either Two(*) or One() (where * refers to either One() or Two(*) objects). Unfortuna\
tely, the code generated by the compiler doesn't detect
sequences of the form: List(Two(*), Two(*)). Here's the output:
default
default
case
default
what expected The expected output is:
default
default
case
case
[back to overview]
Changes of this bug report
Burak  edited on  2004-10-06 16:16:42.0
[changed "with Executable" to "with Application"]
Although this particular instance works, there are still nondeterministic regular expressions that are not treated correctly.
Matthias  edited on  2004-10-12 10:11:26.0
I think the fix pushes the capability of the pattern matcher only one more level. Adding a new alternative to the first pattern exposes exactly the same problem. Here's the code:
case class One();
case class Two(x: Any);
object Main with Application {
  def test(xs: List[Any]) = xs match {
    case List(((Two(One()) | Two(Two(_))), One()) |
              (Two(_), Two(One())) |
              (Two(_), Two(Two(_)))) =>
        Console.println("case");
    case _ =>
        Console.println("default");
  }
  test(List(One(), One()));
  test(List(One(), Two(One())));
  test(List(Two(One()), One()));
  test(List(Two(One()), Two(One())));
  test(List(Two(One()), Two(Two(One()))));
}
This code should produce the following output:
default
default
case
case
case
But currently, it yields default for the last call to test.
Lex  edited on  2006-03-28 13:31:44.0
I have adde "extends Object". Nevertheless, this pattern does not even compile. Should it?
Burak  edited on  2007-07-06 11:40:48.0
I change this test program, in the years past since it was originally submitted, it has come to mean something slightly different. It used to test regexps on lists, but now it tests pairs and alternative patterns (and works).