Skip to content

"unreachable code" false-positives, "match not exhaustive" false-negative warnings when matching on HKTs #11620

Open
@ryan-williams

Description

@ryan-williams

scalafiddle; repros on 2.12.8 and 2.13.0

sealed trait A[+T]
 case class A1[+T](t : T       ) extends A[T]
 case class A2[+T](t1: T, t2: T) extends A[T]

sealed trait B[+T] {
  type AA[+U] <: A[U]
  def a: AA[T]
}
object B {
  type Aux[+_A[+_], +T] = B[T] { type AA[+U] <: _A[U] }
  object Aux {
    def unapply[_A[+U] <: A[U], T](b: Aux[_A, T]): Option[_A[T]] = Some(b.a)
  }
  
  def apply[_A[+U] <: A[U], T](_a: _A[T]): Aux[_A, T] =
    new B[T] { type AA[+U] = _A[U] ; val a: _A[T] = _a }
    
  def unapply[T](b: B[T]): Option[b.AA[T]] = Some(b.a)
}

def foo[T](b: B[T]) = b match {
  case B(A1(t))  t
  case B(A2(t, _))  t
}

def foo2[_A[+U] <: A[U], T](b: B.Aux[_A, T]) = b match {
  case B.Aux(a @ A1(_   ))  a.t
  case B.Aux(a @ A2(_, _))  a.t1  // 👎 (false-positive): unreachable code
}

def foo3[_A[+U] <: A[U], T](b: B.Aux[_A, T]) = b match {
  case B.Aux(a: A1[T])  a.t
  case B.Aux(a: A2[T])  a.t1  // 👎 (false-positive): unreachable code
}

def foo4[T](b: B[T]) = b match {
  case B(A1(t))  t  // 👎 (false-negative): incomplete match
}

val b1: B.Aux[A1, Int] = B(A1(111))
val b2: B.Aux[A2, Int] = B(A2(222, 333))

println(s"${foo (b1)} ${foo (b2)}")
println(s"${foo2(b1)} ${foo2(b2)}")
println(s"${foo3(b1)} ${foo3(b2)}")

Compilation generates false-positive warnings as annotated above:

[warn]       case B.Aux(a @ A2(_, _)) ⇒ a.t1  // 👎 (false-positive): unreachable code
[warn]                                    ^
[warn]       case B.Aux(a: A2[T]) ⇒ a.t1  // 👎 (false-positive): unreachable code
[warn]                                ^

(scalafiddle doesn't display these for some reason)

All three printlns work as expected, reaching the "unreachable code":

111 222
111 222
111 222

The compiler also fails to flag the inexhaustive match in foo4.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions