I caused a bug in my code that was tougher to find that I would have liked, and something that I’d ideally like to avoid in the future. I expected the Scala compiler would have warned me about my error (unless I’m missing something).
I’ve reduced it to the trivial case:
Vector.maybeGetVector match {
case v:Vector => true
case _ => false
}
case class Vector(x:Int, y:Int)
object Vector {
def maybeGetVector : Option[Vector] = Some(new Vector(1,2))
}
The only reason I used wildcard instead of None for the fall through is that I only want to match on a subtype of the returned Option.
I was expecting a compiler warning, as it’s easy to reason that the first case statement contains unreachable code. Option[Vector] can’t be a subtype of Vector.
The strange part is that if I add the following case statement:
case i:Int => false
It raises an error and tells me that Option[Vector] is required.
Is there a way to protect against programmer error in this way, outside of naming conventions. The only things that can ever match against an Option are Some/None/null. I feel I’m missing something obvious.
If you define your Vector class with a
finalmodifier, you’ll get the “pattern type is incompatible with expected type” error you’re expecting.To me that says that Scala thinks your Option[Vector] might somehow be an instance of a subtype of Vector. (This seems impossible to me, but I think that’s the reasoning at work.) Making Vector final precludes that seemingly remote possibility.
So, if the first case statement should be unreachable, it’s not because, as you said, Vector can’t be a subtype of Option[Vector]; but rather because an Option[Vector] can’t be an instance of a subtype of Vector. Maybe that’s what you meant 🙂