It seems that implicit conversions are not in effect in the case of pattern matching.
Consider:
scala> case class Foo(x: Int)
defined class Foo
scala> case class Bar(x: Int)
defined class Bar
scala> implicit def foo2bar(x: Foo) = Bar(x.x)
foo2bar: (x: Foo)Bar
scala> Foo(3) match { case Foo(3) => 3; case _ => 4 }
res19: Int = 3
scala> Foo(3) match { case Bar(3) => 3; case _ => 4 }
<console>:14: error: constructor cannot be instantiated to expected type;
found : Bar
required: Foo
Foo(3) match { case Bar(3) => 3; case _ => 4 }
^
Compare with:
scala> val f: java.lang.Boolean = false
f: Boolean = false
scala> f.<TAB>
asInstanceOf booleanValue compareTo isInstanceOf toString
scala> f || true
res21: Boolean = true
implicit conversions worked here, but not here:
scala> f match { case false => 3; case true => 4 }
<console>:15: error: type mismatch;
found : scala.Boolean(false)
required: java.lang.Boolean
f match { case false => 3; case true => 4 }
^
<console>:15: error: type mismatch;
found : scala.Boolean(true)
required: java.lang.Boolean
f match { case false => 3; case true => 4 }
^
I agree that this is quite counterintuitive but I doubt it could be fixed without introducing a special casing to the language, or making scalac
somehow recognize pattern matches where all patterns belong to a single type, and try to find an implicit conversion to that type. The workaround would be to do an explicit asInstanceOf[Boolean]
cast. Although it's odd that the following works fine:
scala> "foobar".startsWith("foo") match { case true => 3 ; case false => 4 }
res26: Int = 3