-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Narrow types after 'in' operator #4072
Conversation
As discussed in #4099 (comment), let's only do this for optional types, since other cases can be unsafe because of operator overloading, and these other cases seem pretty rare anyway. |
OK, I will do this later this evening or tomorrow morning. |
Done! |
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.
Thanks, looks good! Just a few minor comments.
mypy/checker.py
Outdated
@@ -2874,6 +2874,27 @@ def remove_optional(typ: Type) -> Type: | |||
return typ | |||
|
|||
|
|||
def builtin_item_type(tp: Type) -> Optional[Type]: | |||
# This is only OK for built-in containers, where we know the behavior of __contains__. |
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.
Add docstring.
test-data/unit/check-isinstance.test
Outdated
[case testNarrowTypeAfterInDict] | ||
# flags: --strict-optional | ||
from typing import Dict, Optional | ||
x: Dict[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.
Use a different type for values to make sure that this works against the key type.
# flags: --strict-optional | ||
from typing import List, Optional | ||
|
||
x: List[int] |
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.
Add test for optional item type (e.g. List[Optional[int]]
).
@JukkaL Thanks for review! I implemented the changes in the new commit. |
# flags: --strict-optional | ||
from typing import List, Optional | ||
|
||
x: List[Optional[int]] |
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.
Here's another special case: What if the container is a nested one, say List[List[x]]
, where x
might be Any
? How do we deal with various item types, such as List[int]
and List[Any]
?
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.
a) If the container is List[Any]
, then we do nothing (there is a test for this).
b) If the container is List[List[Any]]
we narrow the type (provided there is an overlap, this is consistent with how ==
currently treated), for example:
x: Optional[int]
lst: Optional[List[int]]
nested: List[List[Any]]
if lst in nested:
reveal_type(lst) # List[int]
if x in nested:
reveal_type(x) # Optional[int]
There is already a test for non-overlapping items int
vs str
. I will add one more test for other (nested) types?
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, added one more test.
Fixes #4071
This is separated from #4070 plus added various tests.