Description
Bug Report
It appears that explicit type definitions of loop variables can be overridden or merged with values inferred from the iterator. Unfortunately this happens even when the iterator type is Any
, somewhat undermining the explicit definition.
To Reproduce
import itertools, typing
class ErrorType:
pass
def report_errors(error_type: ErrorType, id_: object, messages: list[str]) -> None:
pass
errors: list[typing.Any]
source: tuple[ErrorType, object] | None
for source, errors_group in errors:
reveal_type(source) # good: Union[tuple[demo.ErrorType, builtins.object], None]
# bad: Union[tuple[demo.ErrorType, builtins.object], Any]
if source:
reveal_type(source) # good: tuple[demo.ErrorType, builtins.object]
# bad: Union[tuple[demo.ErrorType, builtins.object], Any]
messages: list[str]
report_errors(*source, messages) # bad: Too many arguments for "report_errors"
I've tried reproducing this without the loop, however that seems to make the issue go away.
Removing the messages
argument to report_errors
also seems to avoid the "too many arguments" error, though that doesn't affect the revealed types so I've left it in to give a clearer pass/fail when running mypy
.
Expected Behavior
Under 1.15 and up to 8dd616b the above code passes cleanly with the "good" noted revealed types.
Actual Behavior
From b50f3a1 onwards the above code fails type checking due to the errant message to the report_errors
function, and outputs the "bad" noted revealed types. I'm not familiar enough with mypy to explain why that commit is the cause, however I have narrowed this to that commit using git bisect so I'm fairly confident those changes are related.
Your Environment
Versions as noted above. No command line flags or other config needed.
Python 3.12.3 on Ubuntu 24.04.