Skip to content

Unreachable case when matching with a match type subpattern #13189

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

Closed
Katrix opened this issue Jul 28, 2021 · 2 comments · Fixed by #13251
Closed

Unreachable case when matching with a match type subpattern #13189

Katrix opened this issue Jul 28, 2021 · 2 comments · Fixed by #13251

Comments

@Katrix
Copy link
Contributor

Katrix commented Jul 28, 2021

Compiler version

3.0.1
Did not happen on 3.0.0

Minimized code

trait MyTrait[A] {
  def pack[Z](u: Either[Int, A]): Int
}

def make[ElemTypes <: scala.NonEmptyTuple] = new MyTrait[scala.Tuple.Tail[ElemTypes]] {
  override def pack[Z](u: Either[Int, scala.Tuple.Tail[ElemTypes]]): Int = u match {
    case Left(hz) => ???
    case Right(tz) => ???
  }
}

Output

[error] 214 |      case Right(tz) => ???
[error]     |           ^^^^^^^^^
[error]     |           Unreachable case

Expectation

It compiles

@nicolasstucki
Copy link
Contributor

nicolasstucki commented Jul 28, 2021

Minimized

def foo(opt: Option[Tuple.Tail[NonEmptyTuple]]): Unit =
  opt match
    case None => ???
    case Some(a) => ???
5 |    case Some(a) => ???
  |         ^^^^^^^
  |         Unreachable case

@dwijnand dwijnand changed the title Unreachable case when matching on Either with a match type Unreachable case when matching with a match type subpattern Aug 2, 2021
@dwijnand
Copy link
Member

dwijnand commented Aug 2, 2021

Looks like this is due to:

instantiateToSubType: !(EmptyTuple.type <:< Tuple.Tail[NonEmptyTuple])
object EmptyTuple refined from Tuple.Tail[NonEmptyTuple] to <notype>
...
Tuple.Tail[NonEmptyTuple] decomposes to []

!(EmptyTuple.type <:< Tuple.Tail[NonEmptyTuple]) looks wrong to me, right?


(edit: more trace logging)

decomposable: Tuple.Tail[NonEmptyTuple] = true
candidates for Tuple.Tail[NonEmptyTuple] : [object EmptyTuple, trait NonEmptyTuple]
Subtype trace:
  ==> EmptyTuple.type  <:  Tuple.Tail[NonEmptyTuple]
    ==> EmptyTuple.type  <:  Tuple.Tail[NonEmptyTuple] (recurring)
      ==> EmptyTuple  <:  Tuple.Tail[NonEmptyTuple] (left is approximated)
        ==> EmptyTuple  <:  Tuple.Tail[NonEmptyTuple] (recurring)
          ==> EmptyTuple  <:  NonEmptyTuple match { case _ *: xs => xs } <: Tuple (left is approximated) (right is approximated)
            ==> EmptyTuple  <:  NonEmptyTuple match { case _ *: xs => xs } <: Tuple (recurring)
            <== EmptyTuple  <:  NonEmptyTuple match { case _ *: xs => xs } <: Tuple (recurring) = false
          <== EmptyTuple  <:  NonEmptyTuple match { case _ *: xs => xs } <: Tuple (left is approximated) (right is approximated) = false
        <== EmptyTuple  <:  Tuple.Tail[NonEmptyTuple] (recurring) = false
      <== EmptyTuple  <:  Tuple.Tail[NonEmptyTuple] (left is approximated) = false
      ==> EmptyTuple.type  <:  NonEmptyTuple match { case _ *: xs => xs } <: Tuple (right is approximated)
        ==> EmptyTuple.type  <:  NonEmptyTuple match { case _ *: xs => xs } <: Tuple (recurring)
          ==> EmptyTuple  <:  NonEmptyTuple match { case _ *: xs => xs } <: Tuple (left is approximated) (right is approximated)
            ==> EmptyTuple  <:  NonEmptyTuple match { case _ *: xs => xs } <: Tuple (recurring)
            <== EmptyTuple  <:  NonEmptyTuple match { case _ *: xs => xs } <: Tuple (recurring) = false
          <== EmptyTuple  <:  NonEmptyTuple match { case _ *: xs => xs } <: Tuple (left is approximated) (right is approximated) = false
        <== EmptyTuple.type  <:  NonEmptyTuple match { case _ *: xs => xs } <: Tuple (recurring) = false
      <== EmptyTuple.type  <:  NonEmptyTuple match { case _ *: xs => xs } <: Tuple (right is approximated) = false
    <== EmptyTuple.type  <:  Tuple.Tail[NonEmptyTuple] (recurring) = false
  <== EmptyTuple.type  <:  Tuple.Tail[NonEmptyTuple] = false
object EmptyTuple refined to <notype>
Subtype trace:
  ==> NonEmptyTuple  <:  Tuple.Tail[NonEmptyTuple]
    ==> NonEmptyTuple  <:  Tuple.Tail[NonEmptyTuple] (recurring)
      ==> NonEmptyTuple  <:  NonEmptyTuple match { case _ *: xs => xs } <: Tuple (right is approximated)
        ==> NonEmptyTuple  <:  NonEmptyTuple match { case _ *: xs => xs } <: Tuple (recurring)
        <== NonEmptyTuple  <:  NonEmptyTuple match { case _ *: xs => xs } <: Tuple (recurring) = false
      <== NonEmptyTuple  <:  NonEmptyTuple match { case _ *: xs => xs } <: Tuple (right is approximated) = false
    <== NonEmptyTuple  <:  Tuple.Tail[NonEmptyTuple] (recurring) = false
  <== NonEmptyTuple  <:  Tuple.Tail[NonEmptyTuple] = false
trait NonEmptyTuple refined to <notype>
Tuple.Tail[NonEmptyTuple] decomposes to []

@dwijnand dwijnand linked a pull request Aug 4, 2021 that will close this issue
@Kordyjan Kordyjan added this to the 3.1.1 milestone Aug 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants