Description
The following example defines a simple case class C
with two members and one generic type. Pattern matching on this class gives some surprising results in various cases, and the results differ significantly from 2.12/2.13 behavior. (In fact, all the three cases below are treated differently in Dotty vs. 2.12/2.13):
trait Is[A]
case object IsInt extends Is[Int]
case object IsString extends Is[String]
case class C[A](is: Is[A], value: A)
val c_string: C[String] = C(IsString, "name")
val c_any: C[_] = c_string
val any: Any = c_string
// Case 1: Should give compile error, since IsInt is not compatible with C[String]
c_string match {
case C(IsInt, _) => println(s"An Int") // Can't possibly happen!
case C(IsString, s) => println(s"A String with length ${s.length}")
case _ => println("No match")
}
// Case 2: Should match the second case and print the length of the string
c_any match {
case C(IsInt, i) if i < 10 => println(s"An Int less than 10")
case C(IsString, s) => println(s"A String with length ${s.length}")
case _ => println("No match")
}
// Case 3: Same as above; should match the second case and print the length of the string
any match {
case C(IsInt, i) if i < 10 => println(s"An Int less than 10")
case C(IsString, s) => println(s"A String with length ${s.length}")
case _ => println("No match")
}
In Dotty 0.9.0-RC, only Case 3
is handled as expected (which is the only case that isn't handled correctly in 2.12/2.13). The actual result is that Case 2
fails to compile:
[error] -- [E008] Member Not Found Error: C:\dev\dottytest\src\main\scala\Main.scala:23:28
[error] 23 | case C(IsInt, i) if i < 10 => println(s"An Int less than 10")
[error] | ^^^
[error] | value `<` is not a member of C[_]#A - did you mean `i.==`?
[error] -- [E008] Member Not Found Error: C:\dev\dottytest\src\main\scala\Main.scala:24:64
[error] 24 | case C(IsString, s) => println(s"A String with length ${s.length}")
[error] | ^^^^^^^^
[error] | value `length` is not a member of C[_]#A
[error] two errors found
I would assume the behavior to be:
Case 1
This case should be rejected by the compiler since the IsInt
member is not compatible with C[String]
. But Dotty accepts this, while 2.12 correctly rejects the pattern match due to incompatible types.
Case 2
The type being matched is a C[_]
. 2.12 accepts this pattern match and works as expected, while Dotty does not figure out the type of the corresponding value member. (I am not sure if this is expected in Dotty due to removal of existential types, but it is nevertheless surprising).
Case 3
This compiles and Dotty is able to infer the type of the value based on the case object given as the first parameter. However, in 2.12 this fails (see: Scala 2.12 bug 11132)