-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
0.990 regression with implicit complex/int promotion #14030
Comments
This bug introduces 8 false positives when mypy checks the
|
cc @ilevkivskyi this is from #13781 |
FWIW this is intentional, There is really no middle ground, if we enable promotions, there will be other issues, see, e.g. #6060. I would say current behavior is better because:
|
Also fix should be trivial, use a more precise type, like |
Without strictness flags, the current behavior leads code to be silently skipped as unreachable, which is arguably worse. I agree that there are few good options here though. |
Maybe there's some hack, so we keep the better narrowing behaviour, but it doesn't affect reachability |
@hauntsaninja Actually, if you like hacks, I think there may be a (relatively) easy one: ignore the impossible intersection check in case if one type can be promoted to another one. |
Well, we should probably still prohibit (consider unreachable) something like: if isinstance(x, int) and isinstance(x, float):
... so it may require some work to implement. |
Just making sure you all are aware of the idea in #11516 Specifically: in the if statement, split types up into this union and rely on already-existing narrowing. Y'all are probably already aware, but just making sure this "solution" is considered. (I don't see any reasoning on that issue itself that would disqualify it) |
@hauntsaninja Actually after thinking some more, it seems to me we shouldn't change this, otherwise we may not flag legitimately unreachable code like x = 1j
if isinstance(x, int):
... that may potentially also hide bugs. In general, most of the original motivation for type promotions was that practically all functions originally intended for def weighted(a: float, b: float) -> float:
return (a + 2 * b) / 3
weighted(1, 2) # This is fine
def num_type(x: float) -> str: # Bad, should be Union[int, float]
if isinstance(x, int):
return "Integer"
return "Floating" Anyway, it is still gray area and likely there will still be some people who likes (or used to) the old behavior. So we should clearly document this. |
I agree with Ivan's proposed approach. Some thoughts on what we'd need to change:
|
Some thoughts from me:
|
I think that it would be least confusing if we managed to preserve the I think that it's okay to allow users to be explicit and annotate things as
I don't think that is a significant issue. This is also possible with real subclasses and I don't think anybody has complained about code like this not generating errors: class Base: pass
class Sub(Base): pass
o = Base()
if isinstance(o, Sub):
<something> |
This is different. With |
It was always like this, since both extremes are clearly bad, we need to find a reasonable/clear midpoint. FWIW the current one seems more consistent to me than in 0.982 |
Also in general I am in favor of adding |
I don't want to resurrect those bugs. But I'd specifically like this one to not generate unreachable code: from typing import reveal_type
x: complex = 1
reveal_type(x)
if isinstance(x, int):
reveal_type(x) Requiring
I think that sometimes not detecting unreachable code is less of a problem than code that is silently not being type checked because mypy things that it's unreachable but it really is reachable. I'd expect that the vast majority of users aren't using |
OK, as I said above it is possible with some special casing. The less easy part is how to make the special-casing consistent. e.g. should these two be flagged as unreachable? x: object # Or a union
if isinstance(x, complex) and isinstance(x, int):
...
if isinsatnce(x, complex):
if isinstance(x, int):
... If we continue to flag them as unreachable, then it will be inconsistent with x: complex
if isinsatnce(x, int):
... If we will also make those two reachable, what type will we give to |
Actually, maybe saying all of those are reachable, and |
It seems reasonable to have all of the examples reachable. This could be either way (we can go with whatever is straightforward to implement): x: object # Or a union
if isinsatnce(x, int):
if isinstance(x, complex):
... # Unreachable? |
Given this code:
mypy 0.990:
mypy 0.982:
The 0.982 behavior is correct, since
int
is a subclass ofcomplex
in the static type system.The text was updated successfully, but these errors were encountered: