Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pattern Match Loses Type Information #16885

Closed
adamgfraser opened this issue Feb 10, 2023 · 2 comments
Closed

Pattern Match Loses Type Information #16885

adamgfraser opened this issue Feb 10, 2023 · 2 comments
Labels
itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label

Comments

@adamgfraser
Copy link
Contributor

Compiler version

3.2.2

Minimized code

sealed trait Foo[+A] {
  def baz: A
}

sealed trait Bar[+A] extends Foo[A]

object Bar {
  def unapply[A](bar: Bar[A]): Some[A] =
    Some(bar.baz)
}

def someMethod[A](foo: Bar[A]): A =
  ???

def test[A](foo: Foo[A]): A =
  foo match {
    case bar @ Bar(_) => someMethod(bar)
  }

Output

Found:    (bar : Playground.Foo[A] & Playground.Bar[Any])
Required: Playground.Bar[A]

Expectation

I would expect that the inferred type of bar here would be Bar[A] instead of Bar[Any]. This is the behavior in Scala 2 so this seems to be a regression in type inference

@adamgfraser adamgfraser added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Feb 10, 2023
@smarter
Copy link
Member

smarter commented Feb 10, 2023

This is the behavior in Scala 2 so this seems to be a regression in type inference

Unfortunately, Scala 2's behavior is unsound here:

sealed trait Foo[+A] {
  def foo: A
}

sealed trait Bar[+A] extends Foo[A] {
  def bar: A
}

class FB extends Bar[Any] with Foo[Int] {
  def bar: Any = ""
  def foo: Int = 1
}

object Bar {
  def unapply[A](bar: Bar[A]): Some[A] =
    Some(bar.foo)
}

object Test {
  def test[A](foo: Foo[A]): A =
    foo match {
      case bar @ Bar(_) => bar.bar
    }
  def main(args: Array[String]): Unit = {
    val x: Int = test(new FB) // ClassCastException: String cannot be cast to Integer
    println(x)
  }
}

So I don't think there's anything we can do. See also #11834 where the concept of "invariant refinement" is discussed.

@odersky odersky closed this as completed Feb 11, 2023
@dwijnand
Copy link
Member

Duplicate of #4790

@dwijnand dwijnand marked this as a duplicate of #4790 Feb 21, 2023
@dwijnand dwijnand closed this as not planned Won't fix, can't repro, duplicate, stale Feb 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label
Projects
None yet
Development

No branches or pull requests

4 participants