Considering the following example:
object MatchDuckType {
trait Sup
class Sub1() extends Sup {
def v1: String = "a"
}
def example(v: Any) = {
v match {
case _: Sup { def v1: String } => println(1)
case _ => println(2)
}
}
def main(args: Array[String]): Unit = {
example(Sub1())
example(1)
}
}
The compiler gave the following error:
MatchDuckType.scala:16:12: the type test for xxx.MatchDuckType.Sup{v1: String} cannot be checked at runtime
This statement is clearly wrong, as Sup { def v1: String }
can be easily checked by Java runtime reflection (by first getting the class of the term, then getting its method signatures). Why does the warning still exist? Is it a bug in compiler?
That this doesn't work isn't merely a "bug"; including such a thing in the language would require substantial design, specification, and implementation work.
The feature you were hoping for doesn't exist in either Scala 2 or Scala 3.
I found a feature request for this dating back to 2007 (!), but it never attracted much attention: https://github.com/scala/bug/issues/329
Even if the feature did exist, the feature would be platform-specific and limited in scope: it would only work on the JVM, not on JS or Native, and it would only work for the subset of refinement types that can be faithfully be represented in bytecode. That leaves out a lot of the Scala type system.
(At least without TypeTag
, but TypeTag
is Scala 2-only; the feature request on TypeTag
-based matching is https://github.com/scala/bug/issues/6517 . In a Scala 3 context, consider trying to use match types instead?)
As for your remark about desugaring, pattern matches desugar to isInstanceOf
, and the behavior of isInstanceOf
is the same, so this isn't really about pattern matching per se, it's about type tests.