Skip to content

Union matching not exhaustive or refining #5970

Closed
@milessabin

Description

@milessabin

Compiling the following,

object Test extends App {
  case class Foo[T](t: T)

  def foo[T](ft: T|Foo[T]): T = {
    ft match {
      case Foo(t) => t
      case t => t
    }
  }

  foo(Foo(23))
}

results in,

-- [E007] Type Mismatch Error: tests/run/typeclass-derivation7.scala:6:21 ------
6 |      case Foo(t) => t
  |                     ^
  |          Found:    T$1(t)
  |          Required: T
  |          
  |          where:    T is a type in method foo with bounds >: Test.Foo[T$1]
-- [E007] Type Mismatch Error: tests/run/typeclass-derivation7.scala:7:16 ------
7 |      case t => t
  |                ^
  |                Found:    (T | Test.Foo[T])(t)
  |                Required: T
two errors found

Intuitively the pattern matcher ought to be able to see that the t's on the RHS's of the branches conform to T. If we add type tests,

object Test extends App {
  case class Foo[T](t: T)

  def foo[T](ft: T|Foo[T]): T = {
    ft match {
      case Foo(t: T) => t
      case t: T => t
    }
  }

  foo(Foo(23))
}

The match is reported as not exhaustive and the type tests are reported as uncheckable, despite being intuitively irrefutable.

Replacing the T in the union with Unit eliminates the non-exhaustiveness, but still results in a complaint about uncheckability,

object Test extends App {
  case class Foo[T](t: T)

  def foo[T](ft: Unit|Foo[T]): T = {
    ft match {
      case Foo(t) => t
      case () => ???
    }
  }

  foo(Foo(23))
}
-- Warning: tests/run/typeclass-derivation7.scala:6:11 -------------------------
6 |      case Foo(t) => t
  |           ^^^^^^
  |           the type test for Test.Foo[T] cannot be checked at runtime
one warning found

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions