-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Fix reachability in nested match sequence patterns #19993
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
Open
cdce8p
wants to merge
1
commit into
python:master
Choose a base branch
from
cdce8p:match-sequence-unreachable
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+32
−2
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I... don't really follow. I don't know anything about the pattern matching checker, so I'm just going off inference/comments elsewhere, but isn't it right to say the rest is uninhabited? If I were to guess the problem is more with the
|
rather than the(_, {...})
?(sorry, you'll probably just have to explain why this is right when this comment does that. I just don't get it...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rest type is calculated from the intersection of the subject inner type and the matched inner type. Let's consider an example. Say the subject type is
int | str
and the matched type isint
, the rest type will then bestr
.For
dict
andlist
this is a bit more complicated as those are match patterns itself. So if the subject is{"a": 1, "b": 2}
inferred todict[str, int]
and the case{"a": 2}
the pattern would not actually match. However the inferred matched type is stilldict[str, int]
and the intersection would beNever
which isn't correct. A similar issue happens with list. So we have to ignore the intersection rest type for Mapping and Sequence sub-patterns for those.--
I'm not sure if it might even affect other generic classes as well. So far though I haven't been able to trigger the issue with any other examples so I'd leave it at these two for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK thanks that makes more sense. In that case I'm surprised about the check that rest is uninhabited! But more importantly, it seems like we already have machinery already doing this? (or did I misunderstand your explanation):
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The issue only happens for Mapping or Sequence patterns
inside
a Sequence pattern. Furthermore you'll need a wildcard match. With that mypy currently thinks "oh it's a wildcard so it always matches, thus the rest should be never". That's only true though if the parent sequence pattern itself matches, so we shouldn't infer rest in those cases.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. Is there a reason why this doesn't narrow the 2nd tuple element to
Never
?: (in comparison to ifx
is a dict, which I can see now and is I think what you are talking about)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rest type for
x
is inferred asstr
whereas with the dict example it's inferred asNever
since technically both the subject and inner match types are identicaldict[str, str]
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry I forgot to respond. I'm concerned that the logic here is incomplete, does this PR fix this too?: (I'm specifically concerned about the comparison of
rest
toNever
.)Do you think it would be possible to instead have a marker that actually, if we specify a literal dict literal, it might not actually match? (unless it's empty) Otherwise maybe this is the best we can get...