diff --git a/mypy/checker.py b/mypy/checker.py index a913d2a8eb16..5f72e6f7f399 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -6395,14 +6395,7 @@ def iterable_item_type(self, instance: Instance) -> Type: # in case there is no explicit base class. return item_type # Try also structural typing. - ret_type, _ = self.expr_checker.check_method_call_by_name( - "__iter__", instance, [], [], instance - ) - ret_type = get_proper_type(ret_type) - if isinstance(ret_type, Instance): - iterator = map_instance_to_supertype(ret_type, self.lookup_typeinfo("typing.Iterator")) - item_type = iterator.args[0] - return item_type + return self.analyze_iterable_item_type_without_expression(instance, instance)[1] def function_type(self, func: FuncBase) -> FunctionLike: return function_type(func, self.named_type("builtins.function")) diff --git a/test-data/unit/check-inference.test b/test-data/unit/check-inference.test index fc8113766f1a..cfb553820d9e 100644 --- a/test-data/unit/check-inference.test +++ b/test-data/unit/check-inference.test @@ -380,6 +380,8 @@ class Nums(Iterable[int]): def __iter__(self): pass def __next__(self): pass a, b = Nums() +reveal_type(a) # N: Revealed type is "builtins.int" +reveal_type(b) # N: Revealed type is "builtins.int" if int(): a = b = 1 if int(): @@ -388,6 +390,37 @@ if int(): b = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int") [builtins fixtures/for.pyi] +[case testInferringTypesFromIterableStructuralSubtyping1] +from typing import Iterator +class Nums: + def __iter__(self) -> Iterator[int]: pass +a, b = Nums() +reveal_type(a) # N: Revealed type is "builtins.int" +reveal_type(b) # N: Revealed type is "builtins.int" +if int(): + a = b = 1 +if int(): + a = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int") +if int(): + b = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int") +[builtins fixtures/for.pyi] + +[case testInferringTypesFromIterableStructuralSubtyping2] +from typing import Self +class Nums: + def __iter__(self) -> Self: pass + def __next__(self) -> int: pass +a, b = Nums() +reveal_type(a) # N: Revealed type is "builtins.int" +reveal_type(b) # N: Revealed type is "builtins.int" +if int(): + a = b = 1 +if int(): + a = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int") +if int(): + b = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int") +[builtins fixtures/tuple.pyi] + -- Type variable inference for generic functions -- ---------------------------------------------