Open
Description
https://github.com/mesonbuild/meson/blob/master/mesonbuild/cmake/fileapi.py
This file started triggering:
mesonbuild/cmake/fileapi.py:81:20: error: "None" has no attribute "__iter__" (not iterable) [attr-defined]
mesonbuild/cmake/fileapi.py:82:20: error: Value of type "None" is not indexable [index]
mesonbuild/cmake/fileapi.py:84:36: error: Value of type "None" is not indexable [index]
due to reuse of for i in ......:
Reduction:
import typing as T
from pathlib import Path
for i in Path().iterdir():
T.reveal_type(i)
break
data = T.cast('T.Dict[str, T.Any]', {'foo': [{'kind': 1, 'b': 'two'}]})
for i in data['foo']:
T.reveal_type(i)
assert isinstance(i, dict)
T.reveal_type(i)
assert 'kind' in i
With mypy 1.16.0
$ mypy --no-strict-optional --warn-unreachable fileapi.py
fileapi.py:5: note: Revealed type is "pathlib.Path"
fileapi.py:10: note: Revealed type is "Any"
fileapi.py:12: note: Revealed type is "None"
fileapi.py:13: error: "None" has no attribute "__iter__" (not iterable) [attr-defined]
It starts off as Path, gets redefined as Any (which works?), but then asserting the Any is a dict results in it migrating to None. With mypy 1.15, it never redefined to Any at all, so it became unreachable:
$ pip install mypy==1.15.*
$ mypy --no-strict-optional --warn-unreachable fileapi.py
fileapi.py:5: note: Revealed type is "pathlib.Path"
fileapi.py:10: note: Revealed type is "pathlib.Path"
fileapi.py:11: error: Subclass of "Path" and "dict[Any, Any]" cannot exist: would have incompatible method signatures [unreachable]
fileapi.py:12: error: Statement is unreachable [unreachable]
I can't really say either behavior is useful. I want variables to be block-scoped and reset their expected value. But at least the 1.15 behavior was comprehensible to me. The new behavior only works if I delete the assert, which seems terribly counterproductive.