Aladdin - Scala Bugtracking
[#409] project: compiler priority: high category: bug
submitter assigned to status date submitted
Michel Martin not repro 2005-03-28 11:02:28.0
subject incorrect use of the $tag method
code
abstract class Expr;
case class Case1(x: Int) extends Expr;
case class Case2(x: Int) extends Expr;
case class Case3(x: Int) extends Expr;

class Toto extends Expr with Case1(12);

object Main {
  def f(x: Expr): Int = x match {
    case Case1(x) => x
    case Case2(x) => x
    case Case3(x) => x
  }

  def main(args: Array[String]): Unit = {
    Console.println(f(new Toto));
  }
}
what happened
The program failed with a MatchError exception.
what expected

The program should have printed 12. It does so if one removes the third case class, because then pattern matching is done using calls to isInstanceOf and not $tag.

The problem here is that using the $tag method is wrong, because as soon as one imports a class as a mixin, its tag$ method gets changed. The instance of Toto which is passed to f has a tag which corresponds to its Toto "personality", and the fact that it is also an instance of Case1 goes unnoticed. I fear there is no easy fix.

[back to overview]
Changes of this bug report
Michel  edited on  2005-03-29 08:47:43.0
After re-reading the language definition, it seems to me that we have enough restrictions to make the tag method work correctly, provided we stop attaching it to *every* class, and attach it only to case classes. Since a class can have at most one case class among its base classes, this would ensure that a class has at most one tag method.
Burak  edited on  2005-06-10 18:47:30.0

Reassign to Martin, the $tag method is one of the early phases . In case you still want to fix bugs of old compiler...

This was discussed at least twice in meetings, the problem is not with matching but with the excessive generation of tag methods. They should only be generated for case classes and nothing else, if I remember correctly.

Martin  edited on  2006-03-30 18:15:50.0
The problem is not reproducible for Scala 2 because you can't mix in a case class.