From f9354eb66848ea10ac422affb02b1b13fb2d8cf2 Mon Sep 17 00:00:00 2001 From: dhanusharer Date: Sat, 7 Mar 2026 02:55:55 +0530 Subject: [PATCH 1/5] Fix incorrect type inference for with iterators --- mypy/checkexpr.py | 12 ++++++++++-- test-data/unit/check-functions.test | 11 +++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index c04f0bd2b4fa..a00674fb2694 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1,6 +1,7 @@ """Expression type checker. This file is conceptually part of TypeChecker.""" - from __future__ import annotations +from mypy.types import Instance +from mypy.types import Instance, get_proper_type import enum import itertools @@ -6273,7 +6274,14 @@ def visit_yield_from_expr(self, e: YieldFromExpr, allow_none_return: bool = Fals # Check that the iterator's item type matches the type yielded by the Generator function # containing this `yield from` expression. expected_item_type = self.chk.get_generator_yield_type(return_type, False) - actual_item_type = self.chk.get_generator_yield_type(iter_type, False) + + + iter_type_proper = get_proper_type(iter_type) + + if isinstance(iter_type_proper, Instance) and iter_type_proper.args: + actual_item_type = iter_type_proper.args[0] + else: + actual_item_type = self.chk.get_generator_yield_type(iter_type, False) self.chk.check_subtype( actual_item_type, diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index 699e83ccbd9f..39c3dc266750 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -3768,3 +3768,14 @@ class C: def defer() -> int: return 1 + + +[case testYieldFromIteratorMismatch] +from typing import Generator, Iterator + +class A(Iterator[int]): + def __next__(self) -> int: ... + def __iter__(self) -> "A": ... + +def f() -> Generator[tuple[int, ...], None, None]: + yield from A() # E: Incompatible types in "yield" \ No newline at end of file From 51fa9d0511555ac3d0851dd0f1c6f01a8bdca98c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 6 Mar 2026 21:28:49 +0000 Subject: [PATCH 2/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mypy/checkexpr.py | 8 +++----- test-data/unit/check-functions.test | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index a00674fb2694..31001c14181f 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1,7 +1,6 @@ """Expression type checker. This file is conceptually part of TypeChecker.""" + from __future__ import annotations -from mypy.types import Instance -from mypy.types import Instance, get_proper_type import enum import itertools @@ -6275,13 +6274,12 @@ def visit_yield_from_expr(self, e: YieldFromExpr, allow_none_return: bool = Fals # containing this `yield from` expression. expected_item_type = self.chk.get_generator_yield_type(return_type, False) - iter_type_proper = get_proper_type(iter_type) if isinstance(iter_type_proper, Instance) and iter_type_proper.args: - actual_item_type = iter_type_proper.args[0] + actual_item_type = iter_type_proper.args[0] else: - actual_item_type = self.chk.get_generator_yield_type(iter_type, False) + actual_item_type = self.chk.get_generator_yield_type(iter_type, False) self.chk.check_subtype( actual_item_type, diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index 39c3dc266750..12c0c5ecd2b1 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -3778,4 +3778,4 @@ class A(Iterator[int]): def __iter__(self) -> "A": ... def f() -> Generator[tuple[int, ...], None, None]: - yield from A() # E: Incompatible types in "yield" \ No newline at end of file + yield from A() # E: Incompatible types in "yield" From 2526608d46d476635a9e1683a042a4867fc3fc1b Mon Sep 17 00:00:00 2001 From: dhanusharer Date: Sat, 7 Mar 2026 22:22:16 +0530 Subject: [PATCH 3/5] Fix yield-from type mismatch in iterate_python_lines --- mypy/checkexpr.py | 5 +++++ mypy/report.py | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 31001c14181f..dfd09f6ec705 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1,6 +1,11 @@ """Expression type checker. This file is conceptually part of TypeChecker.""" from __future__ import annotations +<<<<<<< HEAD +======= + +from mypy.types import Instance, get_proper_type +>>>>>>> d76cb3e76 (Fix iterator element type extraction for yield from) import enum import itertools diff --git a/mypy/report.py b/mypy/report.py index 885d077d259e..42af8fc82854 100644 --- a/mypy/report.py +++ b/mypy/report.py @@ -147,7 +147,8 @@ def iterate_python_lines(path: str) -> Iterator[tuple[int, str]]: """Return an iterator over (line number, line text) from a Python file.""" if not os.path.isdir(path): # can happen with namespace packages with tokenize.open(path) as input_file: - yield from enumerate(input_file, 1) + for item in enumerate(input_file, 1): + yield item class FuncCounterVisitor(TraverserVisitor): From d40f547246a776829b99797042f75200fa8f5c5b Mon Sep 17 00:00:00 2001 From: dhanusharer Date: Sat, 7 Mar 2026 21:09:49 +0530 Subject: [PATCH 4/5] Fix iterator element type extraction for yield from --- test-data/unit/check-functions.test | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index 12c0c5ecd2b1..ffafdcd4338b 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -3771,11 +3771,11 @@ def defer() -> int: [case testYieldFromIteratorMismatch] -from typing import Generator, Iterator +from typing import Generator, Iterator,Tuple class A(Iterator[int]): def __next__(self) -> int: ... def __iter__(self) -> "A": ... -def f() -> Generator[tuple[int, ...], None, None]: - yield from A() # E: Incompatible types in "yield" +def f() -> Generator[Tuple[int, ...], None, None]: + yield from A() # E: Incompatible types in "yield" \ No newline at end of file From 1fec8ec17943cbb62b3fd231d7a546e349d36d7a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 7 Mar 2026 16:56:14 +0000 Subject: [PATCH 5/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test-data/unit/check-functions.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index ffafdcd4338b..37d596e86a8a 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -3778,4 +3778,4 @@ class A(Iterator[int]): def __iter__(self) -> "A": ... def f() -> Generator[Tuple[int, ...], None, None]: - yield from A() # E: Incompatible types in "yield" \ No newline at end of file + yield from A() # E: Incompatible types in "yield"