Description
[moved from https://github.com/python/mypy/issues/7371]
The 2-arg form of iter()
takes a callable and a sentinel value. Quoting its docstring:
iter(callable, sentinel) -> iterator
[...], the callable is called until it returns the sentinel.
When the sentinel is the literal None
, this means that a callable that returns an Optional[T]
is transformed into a Iterator[T]
. However, mypy does not detect that, and reveal_type
on the iter()
result claims its Revealed type is 'typing.Iterator[Union[T, None]]'
, which allows for None
values, which is impossible.
Here's a small example:
from typing import Optional
def maybe_int() -> Optional[int]:
return 123 # or maybe None
for n in iter(maybe_int, None):
print(n + n)
Even though n
is always an int
inside the loop (never None
), mypy (version 0.720) is not aware of that, and complains:
error: Unsupported operand types for + ("int" and "None")
error: Unsupported operand types for + ("None" and "int")
error: Unsupported left operand type for + ("None")
Both left and right operands are unions
Since the code is perfectly safe, mypy should infer that n
is of type int
(not Optional[int]
) and should not report any errors about adding int
and None
values.