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
Support narrowing literals and enums using the in operator in combination with tuple expressions. #17044
base: master
Are you sure you want to change the base?
Conversation
…tion with tuple expressions. The general idea is to transform expressions like (x is None) and (x in (1, 2)) and (x not in (3, 4)) into (x is None) and (x == 1 or x == 2) and (x != 3 and x != 4) This transformation circumvents the need to extend the (already complicated) narrowing logic further.
for more information, see https://pre-commit.ci
This comment has been minimized.
This comment has been minimized.
…mypy into feature/narrow_using_in
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
I generally like what you are trying to achieve. But it feels a bit weird that this is the way you approach this. I have recently done a lot of research into the Mypy narrowing code and it feels like the most convoluted and complicated part of the whole Mypy code base. (Other parts like the recently added --new-type-inference are way more approachable even though they are more complex). I therefore understand that you wanted to special case this. However, in this case it feels like the code would be more approachable if it was actually implemented in the Also you handled But then again I'm not a Mypy dev, so they might feel different about this PR. |
@davidhalter Thanks for your opinion on this, which I understand. I started with extending the mentioned Regarding the different ways to narrow from typing import Optional
class A: pass
class B(A): pass
class C(A): pass
y: Optional[B]
if y in (B(), C()):
reveal_type(y) # N: Revealed type is "__main__.B"
else:
reveal_type(y) # N: Revealed type is "Union[__main__.B, None]" But if one uses if y == B() or y == C():
reveal_type(y) # N: Revealed type is "Union[__main__.B, None]"
else:
reveal_type(y) # N: Revealed type is "Union[__main__.B, None]" So, for this aspect, I would say the proposed change increases consistency (always the second result). I might have been too cautious about the Two Mypy primer responses are satisfying (discord), and one needs investigation (mkosi). However, for Mypyc, there seems to be a relevant problem. (I have no Mypyc experience, but my first impression is that the proposed transformation confuses Mypy. Maybe the left operand is only available for the first comparison with the items of the right operand?) |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Diff from mypy_primer, showing the effect of this PR on open source code: discord.py (https://github.com/Rapptz/discord.py)
- discord/app_commands/tree.py:413: error: Missing return statement [return]
- discord/app_commands/tree.py:533: error: Missing return statement [return]
|
The mkosi and mypyc problems are fixed. I also included a small documentation update in case this pull request gets accepted. It's clearly not the most general solution, but it should handle the most frequent use case (at least the one often relevant to me...), so I will wait for a review. |
The general idea is to transform expressions like
into
This transformation circumvents the need to extend the (already complicated) narrowing logic further.
See the test
testNarrowTypeAfterInTuple
, which shows a slight change in the narrowing behaviour. I don't know if this is an improvement, but at least it seems to increase consistency.The only downside of the transformation approach I am aware of is that it might cause some hard-too-understand error messages. The only such problem I encountered is the
Right operand of "and" is never evaluated
warning in thetestNarrowLiteralsNotInTupleExpression
test.