bug
bug copied to clipboard
allow more precise type when matching parametric case classes (or extractors)
Currently it is possible to match a parametric case class with correct type like so:
case class Register[T](key: Key[T], value: T)
...
x match {
case r: Register[t] =>
val k: Key[t] = r.key
val v: t = r.value // matching types with the key
}
What does not work is the same while extracting values (1):
case Register[t](k, v) => // says “Register[t] does not take parameters”
When not including the name for the type, T is inferred to be Any (2):
case Register(k, v) => // T is Any here, even though Register is not covariant
There are two things which should be done:
- allow the extraction syntax shown in (1) above
- implicitly introduce a type with a fresh name when performing the match as in (2), leading to more precise type checking than just assuming Any instead
The second part’s current negative effect can be seen in the following (assuming generic ActorRef[-T] which only accepts messages of type T):
case class Echo[T](msg: T, replyTo: ActorRef[T])
...
x match {
case Echo(msg, replyTo) =>
replyTo ! msg // works by accident now because T=Any for both
replyTo ! 42 // works as well, but should not actually work
}
Imported From: https://issues.scala-lang.org/browse/SI-8901?orig=1 Reporter: @rkuhn See #7886
@retronym said: I believe the unsound inference of T=Any is a duplicate of bug #7886.
Supporting pattern matching type variables in constructor patterns is an interesting idea.
@paulp said: I +/- implemented this (via a macro!) here. It's tricky because the parser generates the wrong tree if you provide type arguments in a constructor pattern - you get an AppliedTypeTree instead of TypeApply, so it must be entirely thrown out and rebuilt.
@milessabin said: @paulp can I persuade you to translate that to a PR against the compiler? As the tests for your macro demonstrate, this gets along very nicely with literal types, and it's something I'd love to see in TLS.
@paulp said: If I opened a PR against the compiler it would only be for the purpose of getting it into the typelevel compiler (since there's no chance of me taking it to completion) which seems like an abuse of the PR queue.
I believe the code is unusually clear and shouldn't be difficult for someone with higher optimism to adapt into a scala PR.
@milessabin said: If you open a PR against scala/scala then I'll commit to getting it across the finishing line. I'm not likely to have time to reimplement this myself anytime soon, so this will be your quickest route to seeing it appear in the Typelevel Scala compiler.
@paulp said: Ok, if I can find the time somewhere.
someone want to check if this is still reproducible in current Scala 2 and/or 3?