Skip to content

Inference failure in return statement with next and or #15755

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
PGijsbers opened this issue Jul 23, 2023 · 1 comment · May be fixed by #18976
Open

Inference failure in return statement with next and or #15755

PGijsbers opened this issue Jul 23, 2023 · 1 comment · May be fixed by #18976
Labels
bug mypy got something wrong

Comments

@PGijsbers
Copy link

PGijsbers commented Jul 23, 2023

The following MWE (mypy-playground):

from typing import Iterator

def this_fails(numbers: Iterator[int]) -> int:
  return next(numbers, None) or 0
  
def intermediate_is_ok(numbers: Iterator[int]) -> int:
  my_number = next(numbers, None) or 0
  return my_number

def separate_line_is_ok(numbers: Iterator[int]) -> int:
  result = next(numbers, None)
  return result or 0
  
def using_default_directly_is_ok(numbers: Iterator[int]) -> int:
  return next(numbers, 0)

def having_optional_int_with_or_is_ok(number_maybe: int | None) -> int:
  return number_maybe or 0

produces the following report on master:

main.py:4: error: Argument 2 to "next" has incompatible type "None"; expected "int"  [arg-type]

This is incorrect as next(numbers, None) or 0 is always int.
All close variants, including assigning it to an intermediate variable, don't have this issue.
I can't think of an actual application where you would want to write code like this, but I figured it's an interesting interaction that might warrant investigation.

I couldn't find an open issue about this and I asked in Gitter.

@PGijsbers PGijsbers added the bug mypy got something wrong label Jul 23, 2023
@PascalPuchtler
Copy link

PascalPuchtler commented Jul 25, 2023

Hey, I am new here.
I worde a *.testfile to have a running and failing test case.
This is my current version

[case testIterator]
# flags: --python-version 3.10
from typing import Iterator
from typing import Iterable
from typing import TypeVar

E = TypeVar("E")
T = TypeVar("T")
def next(x: Iterable[T], default: E) -> T | E: ...

def this_fails(numbers: Iterator[int]) -> int:
  return next(numbers, None) or 0
  
def intermediate_is_ok(numbers: Iterator[int]) -> int:
  my_number = next(numbers, None) or 0
  return my_number

def separate_line_is_ok(numbers: Iterator[int]) -> int:
  result = next(numbers, None)
  return result or 0
  
def using_default_directly_is_ok(numbers: Iterator[int]) -> int:
  return next(numbers, 0)

def having_optional_int_with_or_is_ok(number_maybe: int | None) -> int:
  return number_maybe or 0

The test execution shows the same error as above
main:11: error: Argument 2 to "next" has incompatible type "None"; expected "int" (diff)

Can someone give me a hint, where i can find the implementation method next and or to fix this bug?

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
bug mypy got something wrong
Projects
None yet
2 participants