Skip to content
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

Binder should reason about complex expressions #2199

Open
gvanrossum opened this issue Sep 30, 2016 · 7 comments
Open

Binder should reason about complex expressions #2199

gvanrossum opened this issue Sep 30, 2016 · 7 comments
Labels
false-positive mypy gave an error on correct code feature priority-1-normal topic-type-narrowing Conditional type narrowing / binder

Comments

@gvanrossum
Copy link
Member

gvanrossum commented Sep 30, 2016

Here's a very simple example:

from typing import *
a = ['x', None]  # type: List[Optional[str]]
for i in range(len(a)):
    if a[i]:
        print(i, '<' + a[i] + '>')

We get an error on the last line:

__tmp__.py:5: error: Unsupported operand types for + ("str" and "Optional[str]")

Of course I can refactor this by using

for i in range(len(a)):
    ai = a[i]
    if ai:
        print(i, '<' + ai + '>')

but that's just busy-work and doesn't necessarily make the code more readable.

(I found this in some mypy test code where the actual expression was p[i].arg so this probably needs to become fairly powerful.)

gvanrossum pushed a commit that referenced this issue Sep 30, 2016
This shows several different approaches to dealing with #2199 for
p[i].arg.
@ddfisher
Copy link
Collaborator

Yeah, this looks like a general binder feature to me.

@ddfisher ddfisher changed the title None checking (binder?) should reason about complex expressions Binder should reason about complex expressions Sep 30, 2016
@ddfisher
Copy link
Collaborator

Actually, these things are pretty difficult to do correctly/safely, because you have to worry about e.g.:

from typing import *
a = ['x', None]  # type: List[Optional[str]]
for i in range(len(a)):
    if a[i]:
        a[0] = None  # how do we detect something like this?
        print(i, '<' + a[i] + '>')

@gvanrossum
Copy link
Member Author

I agree it's complicated (and it would be even more complicated if we considered other threads). I'm just pointing out that if we have a lot of code like this (and I've seen a lot of it in Dropbox repos) is all needs to be refactored just to shut up --strict-optional, and that's tedious.

gvanrossum added a commit that referenced this issue Oct 3, 2016
* Fix strict none errors in the test subpackage.

This shows how to deal with #2199 for `p[i].arg`.

* Run mypy over itself in --strict-optional mode. Add mypy.ini to suppress most errors (for now).
@JukkaL
Copy link
Collaborator

JukkaL commented Oct 4, 2016

The binder already isn't safe, so this wouldn't fundamentally change anything. The binder currently seems to handle a[0] but not a[i]. Adding support for the latter hopefully wouldn't be hard. [These only seem to work with isinstance tests. A test such as if a[0]: doesn't seem to be supported, but I assume that it wouldn't be hard to fix.]

Example of unsafety:

from typing import *
a = ['x', 1]  # type: List[Union[int, str]]

for i in range(len(a)):
    if isinstance(a[0], int):
        a[i] = 'x'
        reveal_type(a[0])  # int, even though it's clearly str

@gvanrossum
Copy link
Member Author

gvanrossum commented Oct 4, 2016 via email

@JukkaL
Copy link
Collaborator

JukkaL commented Oct 4, 2016

I have no idea. We could perhaps generate a sample of such things from a large corpus and manually analyze them. I doubt we can reason this from first principles.

@gvanrossum gvanrossum added this to the Future milestone Oct 27, 2016
@gvanrossum gvanrossum removed this from the Future milestone Mar 29, 2017
@ilevkivskyi
Copy link
Member

I agree it's complicated (and it would be even more complicated if we considered other threads). I'm just pointing out that if we have a lot of code like this (and I've seen a lot of it in Dropbox repos) is all needs to be refactored just to shut up --strict-optional, and that's tedious.

There is a lot of code like this in mypy itself: if x[i] is not None: ..., if x.attr is not None: ..., and None not in x (for collections). I think it makes sense to raise priority to normal here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
false-positive mypy gave an error on correct code feature priority-1-normal topic-type-narrowing Conditional type narrowing / binder
Projects
None yet
Development

No branches or pull requests

5 participants