From bf7a76f0d6bb2e44f4b88cc7582c9dd7ac79713e Mon Sep 17 00:00:00 2001 From: AlexWaygood Date: Thu, 2 Mar 2023 21:57:25 +0000 Subject: [PATCH 1/2] Fix `Any` inference when unpacking iterators that return `self` and don't directly inherit from `typing.Iterator` --- mypy/checker.py | 9 +------- test-data/unit/check-inference.test | 34 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index a913d2a8eb16d..5f72e6f7f399d 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 fc8113766f1a9..42cf2c1e192ad 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,38 @@ 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 + 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/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 -- --------------------------------------------- From 6e93052e4d4e163cc5766984ccae28f5b4409b3a Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Fri, 3 Mar 2023 10:23:56 +0000 Subject: [PATCH 2/2] Update test-data/unit/check-inference.test --- test-data/unit/check-inference.test | 1 - 1 file changed, 1 deletion(-) diff --git a/test-data/unit/check-inference.test b/test-data/unit/check-inference.test index 42cf2c1e192ad..cfb553820d9ef 100644 --- a/test-data/unit/check-inference.test +++ b/test-data/unit/check-inference.test @@ -394,7 +394,6 @@ if int(): from typing import Iterator class Nums: def __iter__(self) -> Iterator[int]: 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"