scala3
scala3 copied to clipboard
multiple steps required to diagnose error when matching with an incompatible pattern
Example here is taken from "Hands-on Scala Programming" by @lihaoyi
Problem: if you use a disjoint pattern, then the error is basically delayed until after errors of using bindings inferred as Any from the pattern holes, e.g. trying to extract a Tuple2 with a Tuple3 pattern.
The origin of the error: the wrong pattern, should be prioritised IMO, or at least shown at the same time as the usage error.
Compiler version
3.8.0-RC2
Minimized code
//> using scala 3.8.0-RC2
case class Phrase(isHello: Boolean, place: String)
case class P[T](result: T) {
def map[U](f: T => U): P[U] = ???
}
object Test {
def main(args: Array[String]): Unit =
P(("resultA", "resultB")).map{
case ("hello", spaces, place) => new Phrase(true, place)
}
}
Output
[error] ./foo.scala:12:57
[error] Found: (place : Any)
[error] Required: String
[error] case ("hello", spaces, place) => new Phrase(true, place)
[error] ^^^^^
Expectation
in scala 2.13 its not even allowed to try and match with the pattern:
[error] ./foo.scala:12:12
[error] constructor cannot be instantiated to expected type;
[error] found : (T1, T2, T3)
[error] required: (String, String)
[error] case ("hello", spaces, place) => new Phrase(true, place)
[error] ^
if course in Scala 3 if we remove the use of the binding then the error for the pattern comes through:
[warn] ./foo.scala:12:7
[warn] match may not be exhaustive.
[warn]
[warn] It would fail on pattern case: (_, _)
[warn] case ("hello", spaces, place) => "hello" // new Phrase(true, place)
[warn] ^
[error] ./foo.scala:12:12
[error] this case is unreachable since type (String, String) is not a subclass of class Tuple3
[error] case ("hello", spaces, place) => "hello" // new Phrase(true, place)
[error] ^