python / mypy

Optional static typing for Python
https://www.mypy-lang.org/
Other
18.23k stars 2.79k forks source link

Type-narrowing does not apply across 2 branches having the same condition within the same block #7928

Open syastrov opened 4 years ago

syastrov commented 4 years ago

def my_func() -> bool: return True

created: bool = my_func() a: Optional[int] = None if created: a = 1 z = a + 1 # This is OK

if created: x = a + 1 # Unsupported operand types for + ("None" and "int")


* What is the actual behavior/output?

$ mypy a.py a.py:13: error: Unsupported operand types for + ("None" and "int") a.py:13: note: Left operand is of type "Optional[int]" Found 1 error in 1 file (checked 1 source file)



* What is the behavior/output you expect?

No errors. Mypy should be able to narrow the type of `a` to just `int` in the second `if` block, because it narrowed it to that type already the first `if` block and they have the exact same condition.

You can argue that it's easy to workaround it be merging the `if` blocks, but in real-life code, there could easily be intervening code that is not trivial to move around.

* What are the versions of mypy and Python you are using?
mypy 0.750+dev.5b73e2a5e62d3da723ac517fabacaa2a0c8cdf3c
Python 3.7.4

* What are the mypy flags you are using? (For example --strict-optional)
--strict-optional
msullivan commented 4 years ago

This would be handy in a few situations, but also require a major extension of our narrowing mechanisms for a use case that I don't think is that common.

My inclination is to say we aren't going to do this, though I'm curious what @JukkaL and @ilevkivskyi think about whether its worth leaving open as a feature request.

ilevkivskyi commented 4 years ago

I think it is fine to keep this as a low-priority feature request.

In general I think there is a cluster-issue formed (I think I mentioned this before elsewhere) around cleaning-up the binder, partial types, inferring unions from if-else, moving towards SSA in --allow-redefinition, and generally maybe making binder and related machinery more abstract-interpreter-like. For this I would like to have some pool of potential use-cases we might want to support.