Skip to content

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

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions