You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
sealed trait A[T] { def x: T }
final case class B(x: String) extends A[String]
final case class C(x: Int) extends A[Int]
def f[T](a: A[T]): Unit = {
def v: T = a match { case C(x) => 42 }
a match {
case B(_) | C(_) =>
val v1: T = v
val v2: T = a match { case C(x) => 42 }
()
}
}
the definition of v1 typechecks correctly, but v2 fails:
$ ~/scala/scala-2.13.14/bin/scala adt.scala
adt.scala:10: error: type mismatch;
found : Int(42)
required: T
val v2: T = a match { case C(x) => 42 }
^
The failure is consistent in Scala 2.12, 2.13 and 3.6, but compiling with 3.6 gives a better hint at the problem:
$ ~/scala/scala3-3.6.3-aarch64-apple-darwin/bin/scala adt.scala
Compiling project (Scala 3.6.3, JVM (11))
[error] ./adt.scala:10:42
[error] Found: (42 : Int)
[error] Required: T
[error]
[error] where: T is a type in method f which is an alias of String
[error] val v2: T = a match { case C(x) => 42 }
[error] ^^
The text was updated successfully, but these errors were encountered:
For an alternative pattern case C(_) | B(_), the bounds are first set to >: Int <: Int, and then the constraints are not updated because they are incompatible. That is actually unsound:
scala>sealedtraitA[T] { defx:T }
|finalcaseclassB(x: String) extendsA[String]
|finalcaseclassC(x: Int) extendsA[Int]
scala>deff[T](a: A[T]):T= a match { caseB(_) |C(_) =>"plop" }
scala> f(C(1)) +1
java.lang.ClassCastException:classjava.lang.String cannot be cast to classjava.lang.Integer (java.lang.String and java.lang.Integer are in module java.base of loader 'bootstrap')
at scala.runtime.BoxesRunTime.unboxToInt(BoxesRunTime.java:99)
It's really fascinating that bugs like this are still discovered after so many years.
For the original example with the nested pattern
deff[T](a: A[T]):T= a match {
caseB(_) |C(_) =>
a match { caseC(_) =>42 }
}
I don't know if it's possible to support that. We'd have to know which of the temporary GADT bounds to reset for typing the nested pattern, and for which ones to keep the constraints from the enclosing pattern?
Given
the definition of
v1
typechecks correctly, butv2
fails:The failure is consistent in Scala 2.12, 2.13 and 3.6, but compiling with 3.6 gives a better hint at the problem:
The text was updated successfully, but these errors were encountered: