Closed
Description
Issue
/** A ClassTag[T] can serve as an extractor that matches only objects of type T.
*
* The compiler tries to turn unchecked type tests in pattern matches into checked ones
* by wrapping a `(_: T)` type pattern as `ct(_: T)`, where `ct` is the `ClassTag[T]` instance.
* Type tests necessary before calling other extractors are treated similarly.
* `SomeExtractor(...)` is turned into `ct(SomeExtractor(...))` if `T` in `SomeExtractor.unapply(x: T)`
* is uncheckable, but we have an instance of `ClassTag[T]`.
*/
def unapply(x: Any): Option[T] =
...
This unfortunately is known to break when used with path dependent type.
Example
The following example shows a couple of cases where it fails
trait R {
type Nat
type Succ <: Nat
type Idx
given ClassTag[Nat]
given ClassTag[Succ]
given ClassTag[Idx]
def n: Nat
def one: Succ
}
class RI extens R {
type Nat = Int
type Succ = Int
type Idx = Int
given ClassTag[Nat] = classOf[Integer]
given ClassTag[Succ] = new ClassTag[Integer] {
def runtimeClass = classOf[Integer]
def unapply(x: Any): Option[Succ] = x match
case n: Int if n > 0 => Some(n)
case _ => None
}
given ClassTag[Idx] = classOf[Integer]
def n: Nat = 4
def one: Succ = 1
}
object App {
val r1: R = new RI
val r2: R = new RI
r1.n match {
case n: r2.Nat => // Should not match or should have an unchecked waring
case n: r1.Idx => // Should not match or should have an unchecked waring
case n: r1.Succ => // Should match only if r1.n is an r1.Succ under the constraints set in r1
}
r1.one match {
case n: r2.Nat => // Should not match or should have an unchecked waring
case n: r1.Idx => // Should not match or should have an unchecked waring
case n: r1.Nat => // Ok
}
}