scala / scala3

The Scala 3 compiler, also known as Dotty.
https://dotty.epfl.ch
Apache License 2.0
5.82k stars 1.05k forks source link

Unsound reduction of match type where the scrutinee's prefix is a param ref #20518

Open smarter opened 3 months ago

smarter commented 3 months ago

Compiler version

3.5.1-RC1-bin-20240602-c6fbe6f-NIGHTLY

Minimized code

This is a variation of @EugeneFlesselle's #19746:

trait V:
  type X = this.type match
    case W[x] => x

class W[+Y] extends V

trait Outer[+T]:
  val t: T

object Test:
  extension (self: Any) def as[T]: T =
    def asX(o: Outer[W[Any]]): o.t.X /* <- reduces to Any */ = self
    asX(new Outer[W[T]] { val t = W[T]() }) /* <- reduces to T */

  @main def run =
    0.as[Boolean] // ClassCastException

The fix for #19746 in https://github.com/scala/scala3/commit/0a3497bf7f0ac032f98d36cf1713e8926b5d176c should be generalized to check is(Param) in prefixes too (and maybe that should also apply to TypeRef and not just TermRef).

EugeneFlesselle commented 3 months ago

Related to #20515

smarter commented 3 months ago

Yes indeed, #20515 is likely to require a more general fix.

EugeneFlesselle commented 3 months ago

This is mostly speculative but the problem seems to me to be assuming (t: W[Any]).X =:= (t: W[Any]).type match {...} =:= W[Any] match {...} when the second equality should really just be a subtyping relationship (IIRC the substitution happens before beginning match type reduction).