Why can I have an impossible case in the scala match?
case-class, pattern-matching, scala
Solution
Shortest answer: making `Name` final suffices to persuade the compiler that `zero` is not one. See this issue and environs.
It would warn on a type test, which is an isInstanceOf:
<console>:15: warning: fruitless type test: a value of type CaseMatching.Name cannot also be a CaseMatching.Id
case IdName(_, _: Id) =>
^
but not when testing equality, since equality is universal.
Here's another good one, `case IdName(_, Id) =>`
<console>:15: error: pattern type is incompatible with expected type;
found : CaseMatching.Id.type
required: CaseMatching.Name
Note: if you intended to match against the class, try `case _: Id`
case IdName(_, Id) =>
^
What you want is:
scala> IdName(Id(0), Name("A")) match { case IdName(_, id: Id.zero.type) => }
<console>:21: warning: fruitless type test: a value of type Name cannot also be a Id (the underlying of Id.zero.type)
IdName(Id(0), Name("A")) match { case IdName(_, id: Id.zero.type) => }
^
The singleton type contains only that value, so it uses `eq` for the test; and as a type test, it also warns. (It uses `eq` instead of `equals` as of this week.)
Not sure how far this goes for you, but:
scala> :pa
// Entering paste mode (ctrl-D to finish)
sealed trait Id { def value: Long }
case class Nonzero(value: Long) extends Id
case object Zero extends Id { val value = 0L }
case class Name(value: String)
case class IdName(id: Id, name: Name)
// Exiting paste mode, now interpreting.
scala> IdName(Zero, Name("A")) match { case IdName(_, Zero) => 1 }
<console>:14: error: pattern type is incompatible with expected type;
found : Zero.type
required: Name
IdName(Zero, Name("A")) match { case IdName(_, Zero) => 1 }
^
Problem
In the example below, in the second `case` I would expect the same compile error as in the first `case`, but it compiles. Why? ``` object CaseMatching extends App { case class Id(value: Long) object Id { val zero = Id(0) } case class Name(value: String) case class IdName(id: Id, name: Name) IdName(Id(0), Name("A")) match { case IdName(_, Id(0) ) => // does not compile (as expected) case IdName(_, Id.zero) => // does compile (but should not ?) case IdName(Id.zero, _) => println("OK") // this is OK and will match case _ => } } ``` Why is it relevant? - It took me the larger part of an hour to find out why the following case was never met: `case TreeEntry(_, Some(child), _, _, NodeType.DIR, _, _)` That was, because the NodeType is in the 4th field and not in the 5th field. I would have appreciated if the compiler had told me!