-
-
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
Type inference for narrowing of unions #1436
Comments
This works for me already without a cast (in Python 3 mode):
Can you give a full example and command line where the cast is required? |
Ah, you're right. I reduced this from a more complicated condition and didn't test the reduced version properly. |
OK, here's a better reduction. The error is in python 2 mode, presumably because the nested
I've gone through a number of iterations on the condition here; I'm not sure what the right way to express it is. It's an edge case in that it wants to deal with character data, but it needs to call into python 2 APIs that deal exclusively in native Here's one that seems to work in a single if statement without an explicit cast in both 2 and 3:
|
Clearly some part of mypy knows that PY3 is false (when run in Python 2
mode). It's possible that the union-sinstance-checking code doesn't know
this and doesn't realize there are only two branches.
|
@gvanrossum You are probably right. Mypy thinks that the else block of the outermost if statement (which is empty) might be taken even in Python 2 mode, even though the if block is always executed. |
Both original and new examples work correctly on master and |
I know this is closed, but right now on Python3 and using conditional expressions, I'm getting wrong type inference on a union type:
I've written comments stating what the type of ret_val_n is inferred to in each case. In the else clause of the conditional expressions, arg remains of Union type, rather than resolving to the remaining type. |
@Krumpet That's a separate issue -- currently we don't do conditional types in branches of ternary expressions ( |
[me]
It's somewhere in the tracker but I can't find the issue because the keywords ("conditional", "termary", "union") are too common to be of much value in searching the tracker. (@ilevkivskyi maybe you recall the issue or how to find it?) |
@gvanrossum I think you (and @Krumpet) want #5550. I found it by remembering Benjamin Peterson opened #5671 and following the link, which is definitely not ideal... |
Maybe, though that's about unreachable code (e.g. |
@Krumpet you example just works (I just tried on a recent git commit). I removed all comments and mypy correctly inferred |
@ilevkivskyi I added the type comments to illustrate where I was getting behavior I didn't expect, they were added after the fact. For me ret_val_2 is still inferred as Union (and arg is also a Union in the else clause for 1 and 2) If mypy inferrs types correctly then at least we've narrowed down the problem to my IDE (pycharm). As you've mentioned on #5550 , PEP 484 doesn't specify supporting type inference in ternary expressions, and that is probably why I'm seeing this behavior on my end. I'll raise this issue with them. |
From #1141 (comment)
This pattern is the most common cause of
cast()
calls in my code, and it would also be awesome if mypy could infer this narrowing on its own so I wouldn't need the explicit cast (although it may be too much to ask).The logic would be that in the (implied)
else
branch of theif
, we know thatx
is notbytes
, so it must be of typeUnion[str, bytes] - bytes = Union[str] = str
. After executing the assignment in theif
branch, we also know that it is of typestr
there. The type checker could construct a new union from the types that are possible in each branch of theif
, which in this case would simplify tostr
.On the other hand, this is currently legal and would become illegal if the union were automatically narrowed in this way:
The text was updated successfully, but these errors were encountered: