Skip to content
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

Fix narrowing unions in tuple pattern matches #17109

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

edpaget
Copy link
Contributor

@edpaget edpaget commented Apr 9, 2024

Allows sequence pattern matching of tuple types with union members to use an unmatched pattern to narrow the possible type of union member to the type that was not matched in the sequence pattern.

For example given a type of tuple[int, int | None] a pattern match like:

match tuple_type:
    case a, None:
         return
    case t:
         reveal_type(t) # narrows tuple type to tuple[int, int]
         return

The case ..., None sequence pattern match can now narrow the type in further match statements to rule out the None side of the union.

This is implemented by moving the original implementation of tuple narrowing in sequence pattern matching since its functionality should be to the special case where a tuple only has length of one. This implementation does not hold for tuples of length greater than one since it does not account all combinations of alternative types.

This replaces that implementation with a new one that builds the rest type by iterating over the potential rest type members preserving narrowed types if they are available and replacing any uninhabited types with the original type of tuple member since these matches are only exhaustive if all members of the tuple are matched.

Fixes #14731

Allows sequence pattern matching of tuple types with union members to
use an unmatched pattern to narrow the possible type of union member to
the type that was not matched in the sequence pattern.

For example given a type of `tuple[int, int | None]` a pattern match
like:

```
match tuple_type:
    case a, None:
         return
    case t:
         reveal_type(t) # narrows tuple type to tuple[int, int]
         return
```

The case ..., None sequence pattern match can now narrow the type in
further match statements to rule out the None side of the union.

This is implemented by moving the original implementation of tuple
narrowing in sequence pattern matching since its functionality should be
to the special case where a tuple only has length of one. This
implementation does not hold for tuples of length greater than one since
it does not account all combinations of alternative types.

This replace that implementation with a new one that  builds the rest
type by iterating over the potential rest type members preserving
narrowed types if they are available and replacing any uninhabited types
with the original type of tuple member since these matches are only
exhaustive if all members of the tuple are matched.

Fixes python#14731
Copy link
Contributor

github-actions bot commented Apr 9, 2024

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

@edpaget
Copy link
Contributor Author

edpaget commented Aug 19, 2024

Hi all, anyone I could work with to get this reviewed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Narrowing and exhaustiveness errors when matching on a tuple of optionals
1 participant