-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Fix Type Comparison Edge Cases #20277
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
base: master
Are you sure you want to change the base?
Conversation
This comment has been minimized.
This comment has been minimized.
|
I don't quite understand what I should do with |
A5rocks
left a comment
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'm not familiar with this part of mypy (this is the first time I saw TypeRange!), so my comments may be wrong. Initial pass through though.
I'm not sure about the bigger picture here, it feels somewhat hacky to rely on type(x) == Y logic to handle type(x) == type(y). I don't have any better ideas though.
This comment has been minimized.
This comment has been minimized.
|
Thanks for the PR! Also, just a short remark/question without any deep knowledge of the matter: If I understand #20275 correctly, calling |
|
@tyralla: Let me know if this makes it clear or if any of that doesn't make sense. |
|
Huh, then couldn't we get rid of any special casing for looking for specifically I imagine it's a bit strange (e.g. (I guess the flaw is actually that we need to know the relevant name to know what to narrow. Maybe that's why we don't do that) |
|
I never really thought about type narrowing with If I look at this example: class X: x = 1
class Y: y = 1
class Z(X, Y): ...
z = Z()
x: X = z
y: Y = z
if x is y:
x.y + y.x # error: "X" has no attribute "y"
# error: "Y" has no attribute "xI ask myself if Mypy should not handle it like: if isinstance(x, type(y)) and isinstance(y, type(x)):
x.y + y.xWhich could eventually easily be implemented with the help of |
I had a look at this and I've modified the implementation to allow this kind of checking. It just needs a bit of cleaning up. |
|
This cannot be directly handled here because class X: x = 1
class Y: y = 1
class Z(X, Y): ...
z = Z()
x: X = z
y: Y = z
if type(x) is type(y): # instead of x is y
x.y + y.x |
|
|
|
|
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: pandas (https://github.com/pandas-dev/pandas)
+ pandas/core/arrays/base.py:1502: error: Redundant cast to "ExtensionArray" [redundant-cast]
ibis (https://github.com/ibis-project/ibis)
- ibis/common/patterns.py:658: error: "Pattern" has no attribute "type" [attr-defined]
- ibis/common/patterns.py:934: error: "Pattern" has no attribute "patterns" [attr-defined]
jax (https://github.com/google/jax)
+ jax/_src/interpreters/partial_eval.py:96: error: Unused "type: ignore" comment [unused-ignore]
+ jax/_src/interpreters/partial_eval.py:99: error: No overload variant of "get" of "dict" matches argument types "int | DArray | Tracer | Var | DBIdx | InDBIdx | OutDBIdx", "int | DArray | Tracer | Var | DBIdx | InDBIdx | OutDBIdx" [call-overload]
+ jax/_src/interpreters/partial_eval.py:99: note: Possible overload variants:
+ jax/_src/interpreters/partial_eval.py:99: note: def get(self, Name, None = ..., /) -> DBIdx | None
+ jax/_src/interpreters/partial_eval.py:99: note: def get(self, Name, DBIdx, /) -> DBIdx
+ jax/_src/interpreters/partial_eval.py:99: note: def [_T] get(self, Name, _T, /) -> DBIdx | _T
+ jax/_src/interpreters/batching.py:231: error: Unused "type: ignore" comment [unused-ignore]
+ jax/_src/interpreters/batching.py:232: error: Unused "type: ignore" comment [unused-ignore]
+ jax/_src/interpreters/batching.py:234: error: No overload variant of "get" of "dict" matches argument types "int | DArray | Tracer | Var | DBIdx | InDBIdx | OutDBIdx", "int | DArray | Tracer | Var | DBIdx | InDBIdx | OutDBIdx" [call-overload]
+ jax/_src/interpreters/batching.py:234: note: Possible overload variants:
+ jax/_src/interpreters/batching.py:234: note: def get(self, Name, None = ..., /) -> DBIdx | None
+ jax/_src/interpreters/batching.py:234: note: def get(self, Name, DBIdx, /) -> DBIdx
+ jax/_src/interpreters/batching.py:234: note: def [_T] get(self, Name, _T, /) -> DBIdx | _T
+ jax/_src/interpreters/batching.py:258: error: Unused "type: ignore" comment [unused-ignore]
rotki (https://github.com/rotki/rotki)
+ rotkehlchen/history/events/structures/base.py:161: error: Unused "type: ignore" comment [unused-ignore]
+ rotkehlchen/history/events/structures/base.py:162: error: Unused "type: ignore" comment [unused-ignore]
+ rotkehlchen/history/events/structures/base.py:163: error: Unused "type: ignore" comment [unused-ignore]
+ rotkehlchen/history/events/structures/base.py:164: error: Unused "type: ignore" comment [unused-ignore]
+ rotkehlchen/history/events/structures/base.py:165: error: Unused "type: ignore" comment [unused-ignore]
+ rotkehlchen/history/events/structures/base.py:166: error: Unused "type: ignore" comment [unused-ignore]
+ rotkehlchen/history/events/structures/base.py:167: error: Unused "type: ignore" comment [unused-ignore]
+ rotkehlchen/history/events/structures/base.py:168: error: Unused "type: ignore" comment [unused-ignore]
+ rotkehlchen/history/events/structures/base.py:169: error: Unused "type: ignore" comment [unused-ignore]
+ rotkehlchen/history/events/structures/base.py:170: error: Unused "type: ignore" comment [unused-ignore]
+ rotkehlchen/history/events/structures/base.py:171: error: Unused "type: ignore" comment [unused-ignore]
+ rotkehlchen/history/events/structures/base.py:172: error: Unused "type: ignore" comment [unused-ignore]
pip (https://github.com/pypa/pip)
+ src/pip/_internal/utils/misc.py:551: error: Redundant cast to "HiddenText" [redundant-cast]
|
Fixes #20275 and #20041
This code snippet fails to type-check before this PR:
But type-checks afterwards.
This is done by finding a least type as the upper bound when the equality succeeds.