Skip to content

Exhaustiveness checker accepts (_, _) but rejects equivalent concrete types in tuple match #4937

@SeanTAllen

Description

@SeanTAllen

Description

When using match \exhaustive\ on a tuple of union types, the exhaustiveness checker accepts (_, _) as a final catch-all pattern but rejects (None, None) in the same position — even when None is the only remaining possibility for each tuple element.

Example that works

type A is String

actor Main
  new create(env: Env) =>
    let x: (A | None) = None
    let y: (A | None) = None

    match \exhaustive\ (x, y)
    | (let a: A, _) => env.out.print("1")
    | (_, let a: A) => env.out.print("2")
    | (_, _) => env.out.print("3")
    end

Example that fails

The only change is (None, None) instead of (_, _):

type A is String

actor Main
  new create(env: Env) =>
    let x: (A | None) = None
    let y: (A | None) = None

    match \exhaustive\ (x, y)
    | (let a: A, _) => env.out.print("1")
    | (_, let a: A) => env.out.print("2")
    | (None, None) => env.out.print("3")
    end
Error:
main.pony:9:5: match marked \exhaustive\ is not exhaustive
    match \exhaustive\ (x, y)
    ^

Expected behavior

Both versions should be accepted. After the first two patterns cover all cases where at least one element is A, the only remaining combination is (None, None). The checker should recognize that (None, None) covers the same remaining space as (_, _) in this context.

Environment

ponyc 0.61.0 on Linux x86_64.

Metadata

Metadata

Assignees

Labels

discuss during syncShould be discussed during an upcoming sync

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions