-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Fixes to union simplification, isinstance and more (try 2) #3086
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
Conversation
The main change is that unions containing Any are no longer simplified to just Any. Also union simplification now has a deterministic result unlike previously, when result could depend on the order of items in a union (this is true modulo remaining bugs). This required changes in various other places to keep the existing semantics, and resulted in some fixes to existing test cases. I also had to fix some tangentially related minor bugs that were triggered by the other changes. We generally don't have fully constructed TypeInfos so we can't do proper union simplification during semantic analysis. Just implement simple-minded simplification that deals with the cases we care about. Fixes #2978. Fixes #1914.
Now this should fix #1850 as well. |
@ilevkivskyi Do you have time to review this (at least the delta from #3025)? |
@gvanrossum I can do this tomorrow morning. |
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 for a delay with my review. Here are few minor additional comments/questions.
# E: Revealed type is 'builtins.list[builtins.float]' | ||
reveal_type(l) \ | ||
# E: Revealed type is 'builtins.list[Union[builtins.bool, builtins.int, builtins.float]]' | ||
[builtins fixtures/list.pyi] |
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.
It would also add a test in the spirit of #2861, involving an additional type (e.g. str
):
from typing import List, Union
a = [''] # type: List[Union[str, List[Union[int, float, bool]]]]
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.
Added
mypy/binder.py
Outdated
and (not isinstance(declared_type, UnionType) | ||
or not any(isinstance(item, NoneTyp) for item in declared_type.items))): | ||
# Assigning an Any value doesn't affect the type to avoid false negatives, unless | ||
# there is an Any item in a declared union type. |
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.
Do you mean "unless there is a None item in a declared union type"? (because you are checking for NoneTyp
)
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 comment was correct -- updated
[case testInferOptionalAnyType] | ||
from typing import Any | ||
x = None | ||
a = None # type: 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.
Is this issue specific to Union[None, Any]
or to arbitrary declared optional type? In the latter case I would another test case with int
instead of Any
in the declared type.
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.
Added test cases for non-optional union type and a union type without Any
items
The crash in |
Actually I think I introduced those when I did a careless merge. |
test-data/unit/check-unions.test
Outdated
if bool(): | ||
x = a | ||
# TODO: Maybe we should infer Any as the type instead. | ||
reveal_type(x) # E: Revealed type is '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.
Do we need a TODO item also here? I think the TODO item in the test above is enough, since we already have Any
here. Or am I missing something?
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.
Nope, that was due to copy-paste
I think this is ready now. I am going to merge it when the tests pass. Please stop me if you think it is not ready yet. |
This is good to go. |
This is an updated version of #3025 with an extra fix for strict-optional mode.