- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Seq/String/Array pattern matches: proposed solution
Tue, 2010-02-09, 21:29
I have this suspicion that we've been overthinking this. This was
almost too easy, so I'm afraid I'm overlooking something, but it looks
good to me. Here are three bits of code, all of which match in 2.7, two
of which fail in 2.8 and throw runtime errors, or would fail silently
were there a default case. After my proposed patch, instead we get
this:
scala> "bob".reverse match { case Seq('b', 'o', 'b') => true }
:5: error: pattern type is incompatible with scrutinee ;
found : Seq[A]
required: String
"bob".reverse match { case Seq('b', 'o', 'b') => true }
^
scala> "bob".toArray match { case Seq('b', 'o', 'b') => true }
:5: error: pattern type is incompatible with scrutinee ;
found : Seq[A]
required: Array[Char]
"bob".toArray match { case Seq('b', 'o', 'b') => true }
^
scala> "bob".toList match { case Seq('b', 'o', 'b') => true }
res2: Boolean = true
Failing seems like outright desirable behavior to me. I built the
compiler with my change and 4 tests fail. Let's see what they are.
1) files/pos/t0999.scala no longer compiles. Feature. It will never
match. Test case only exists looking for a crasher (or so I infer based
on the fact that it crashes scala 2.7.0.)
object A {
val d: Double = Math.sqrt(5 match {
case x: Double => x
})
}
2) files/pos/bug0646.scala no longer compiles. Feature. It will never
match.
new NodeSeq { val theSeq = books.child } match {
case t @ Blabla => t
}
3) files/neg/bug1878.scala has an extra error. Feature. It will never
match, and the test only exists looking for a crasher.
val err1 = "" match { case Seq(f @ _*, ',') => f }
4) files/run/withIndex.scala does not compile. This is the only
legitimate error. It has something to do with Arrays and underscores,
because the same construct with Lists matches fine. Basically, it is:
scala> Array(("a",0)) match { case _: Array[(_, _)] => true }
:5: error: pattern type is incompatible with scrutinee ;
found : Array[(_, _)]
required: Array[(java.lang.String, Int)]
Array(("a",0)) match { case _: Array[(_, _)] => true }
^
Oh yes, the patch. All of two lines. In inferTypedPattern, right after
widening pt0, add:
if (!(pt <:< pattp) && pt.typeSymbol.isEffectivelyFinal)
error(pos, "pattern type is incompatible with scrutinee "+foundReqMsg(pattp, pt0))
Tue, 2010-02-09, 23:07
#2
Re: Seq/String/Array pattern matches: proposed solution
On Tue, Feb 09, 2010 at 10:01:58PM +0100, martin odersky wrote:
> We could think about adding a rule like what you propose to the spec.
> But to go ahead with this, we need a precise wording of such a rule
> (typeSymbol being effectively final does not have a spec counterpart
> so far).
Whenever I look at the spec I am reminded of my limited spec writing
skills. If I try to directly reverse engineer the gist of what it would
say, let's see, the scrutinee's type is "effectively final" if it is:
a) an object or
b) a class if it is also any of:
1) final
2) private
I'm not sure the other possibilities are even relevant to classes, in
which case I could use a simpler finality test. Classes seem to always
have package owners when I look. (Are the specifics of what can own
what documented somewhere? My knowledge on that point is osmotic.)
3) isLocal ("owner is term")
4) owner is object or final class.
I can try to write the first part in spec-ese if you like (if it is in
fact sufficient) but I'm afraid it will be comically inept and not end
up saving effort.
> Also the 4th test case needs to be resolved, if not that's a blocker.
I intended it as such, but I'm always slow to figure out the underscore
bugs so I figured I'd solicit an opinion first. I'll see if I can
figure it out.
Hi Paul,
This looks promising.
We could think about adding a rule like what you propose to the spec.
But to go ahead with this, we need a precise wording of such a rule
(typeSymbol being effectively final does not have a spec counterpart
so far). Also the 4th test case needs to be resolved, if not that's a
blocker.
Cheers