Skip to content

mypy incorrectly narrows variables when used as a 'for' statement index #16321

Closed
@Hnasar

Description

@Hnasar

Bug Report

When iterating over an empty iterable with afor loop , the index isn't defined. If the index is a predefined variable, it is left unchanged. Mypy, however always infers the iterable is never empty and the index is always overwritten. This causes a divergence between static analysis and runtime behavior.

(I initially found this via a false positive truthy-bool error)

To Reproduce

# example.py
from typing import *

l: list[str] = []
x: str | int = 5
for x in l:
    pass
reveal_type(x)  # Revealed type is "builtins.str" -- expected `str | int`

# python3.11 example.py 
# Runtime type is 'int'

https://mypy-play.net/?mypy=master&python=3.11&gist=eecaaa80bc226778521644f9dedbda5b

Expected Behavior

mypy should infer x: str inside the for statement body, but outside, it should infer the original value or'd with the type of the iterable. In this example it should be str | int

Actual Behavior

mypy infers str whereas at runtime it is int.

Your Environment

  • Mypy version used: master, 1.6.1, 1.5.1
  • Mypy command-line flags: N/A
  • Mypy configuration options from mypy.ini (and other config files): N/A
  • Python version used: 3.11

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrong

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions