python / mypy

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

Failure to narrow down type of elements of Tuple #9159

Open MaxG87 opened 4 years ago

MaxG87 commented 4 years ago

_T = TypeVar("_T") _U = TypeVar("_U")

def promote_optional(tup: Tuple[Optional[_T], Optional[_U]]) -> Optional[Tuple[_T, _U]]: for val in tup: if val is None: return None return tup

def promote_optional2(tup: Tuple[Optional[_T], Optional[_U]]) -> Optional[Tuple[_T, _U]]: if tup[0] is None: return None if tup[1] is None: return None return tup


* What is the actual behavior/output?

/tmp/mwe.py:11: error: Incompatible return value type (got "Tuple[Optional[_T], Optional[_U]]", expected "Optional[Tuple[_T, _U]]") /tmp/mwe.py:19: error: Incompatible return value type (got "Tuple[Optional[_T], Optional[_U]]", expected "Optional[Tuple[_T, _U]]") Found 2 errors in 1 file (checked 1 source file)



* What is the behavior/output you expect?
Mypy should accept the code.

* What are the versions of mypy and Python you are using?
mypy 0.782

I want to turn a `Tuple[Optional...]` to an `Optional[Tuple]`, because the whole tuple is worthless if it contains any `None`. Unfortunately Mypy seems to be unable to detect that I checked all elements of the tuple for being none.
JukkaL commented 4 years ago

The first case is too difficult for mypy to figure out. It may be feasible to fix the false positive in the second case.

Akuli commented 4 years ago

I guess this would also be too difficult for mypy to figure out?

def promote_optional(tup: Tuple[Optional[_T], Optional[_U]]) -> Optional[Tuple[_T, _U]]:
    if None in tup:
        return None
    return tup