8000 two-arg iter() with None sentinel does not remove ‘Optional’ · Issue #3201 · python/typeshed · GitHub
[go: up one dir, main page]

Skip to content
two-arg iter() with None sentinel does not remove ‘Optional’ #3201
Closed
@wbolster-eiq

Description

@wbolster-eiq

[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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0