From f1e32c6c7caa76752474eb2ed04b6f8883339e3a Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Wed, 21 Jun 2023 14:24:32 -0700 Subject: [PATCH 1/4] test case --- test-data/unit/check-async-await.test | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/test-data/unit/check-async-await.test b/test-data/unit/check-async-await.test index 83a66ef4a815..d0df2c9e0104 100644 --- a/test-data/unit/check-async-await.test +++ b/test-data/unit/check-async-await.test @@ -945,17 +945,21 @@ async def bar(x: Union[A, B]) -> None: [typing fixtures/typing-async.pyi] [case testAsyncIteratorWithIgnoredErrors] -from m import L +import m -async def func(l: L) -> None: +async def func(l: m.L) -> None: reveal_type(l.get_iterator) # N: Revealed type is "def () -> typing.AsyncIterator[builtins.str]" reveal_type(l.get_iterator2) # N: Revealed type is "def () -> typing.AsyncIterator[builtins.str]" async for i in l.get_iterator(): reveal_type(i) # N: Revealed type is "builtins.str" + reveal_type(m.get_generator) # N: Revealed type is "def () -> typing.AsyncGenerator[builtins.int, None]" + async for i2 in m.get_generator(): + reveal_type(i2) # N: Revealed type is "builtins.int" + [file m.py] # mypy: ignore-errors=True -from typing import AsyncIterator +from typing import AsyncIterator, AsyncGenerator class L: async def some_func(self, i: int) -> str: @@ -968,6 +972,9 @@ class L: if self: a = (yield 'x') +async def get_generator() -> AsyncGenerator[int, None]: + yield 1 + [builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] From 4c3d5f41d3610152a2742dc7761f3ba45a3529fd Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Wed, 21 Jun 2023 14:26:58 -0700 Subject: [PATCH 2/4] fix strip --- mypy/fastparse.py | 53 +++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 902bde110421..a46313fea767 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -521,7 +521,8 @@ def translate_stmt_list( return [block] stack = self.class_and_function_stack - if self.strip_function_bodies and len(stack) == 1 and stack[0] == "F": + # Fast case for stripping function bodies + if can_strip and self.strip_function_bodies and len(stack) == 1 and stack[0] == "F" and not is_coroutine: return [] res: list[Statement] = [] @@ -529,32 +530,30 @@ def translate_stmt_list( node = self.visit(stmt) res.append(node) - if ( - self.strip_function_bodies - and can_strip - and stack[-2:] == ["C", "F"] - and not is_possible_trivial_body(res) - ): - # We only strip method bodies if they don't assign to an attribute, as - # this may define an attribute which has an externally visible effect. - visitor = FindAttributeAssign() - for s in res: - s.accept(visitor) - if visitor.found: - break - else: - if is_coroutine: - # Yields inside an async function affect the return type and should not - # be stripped. - yield_visitor = FindYield() - for s in res: - s.accept(yield_visitor) - if yield_visitor.found: - break - else: - return [] - else: - return [] + # Slow case for stripping function bodies + if can_strip and self.strip_function_bodies: + if stack[-2:] == ["C", "F"] and not is_possible_trivial_body(res): + # We only strip method bodies if they don't assign to an attribute, as + # this may define an attribute which has an externally visible effect. + visitor = FindAttributeAssign() + for s in res: + s.accept(visitor) + if visitor.found: + can_strip = False + break + + if can_strip and is_coroutine: + # Yields inside an async function affect the return type and should not + # be stripped. + yield_visitor = FindYield() + for s in res: + s.accept(yield_visitor) + if yield_visitor.found: + can_strip = False + break + + if can_strip: + return [] return res def translate_type_comment( From 4ff12c34308c3bcf8039e8db02b4ad1db3afed3e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 21 Jun 2023 21:30:00 +0000 Subject: [PATCH 3/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mypy/fastparse.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index a46313fea767..b157fd9722d4 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -522,7 +522,13 @@ def translate_stmt_list( stack = self.class_and_function_stack # Fast case for stripping function bodies - if can_strip and self.strip_function_bodies and len(stack) == 1 and stack[0] == "F" and not is_coroutine: + if ( + can_strip + and self.strip_function_bodies + and len(stack) == 1 + and stack[0] == "F" + and not is_coroutine + ): return [] res: list[Statement] = [] From 73a77b306cb60c01ed899845560dd4063ba5d624 Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Wed, 21 Jun 2023 15:06:50 -0700 Subject: [PATCH 4/4] fix empty body bug, extra caution for async strip --- mypy/fastparse.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index b157fd9722d4..fe59ff48bdfc 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -538,17 +538,20 @@ def translate_stmt_list( # Slow case for stripping function bodies if can_strip and self.strip_function_bodies: - if stack[-2:] == ["C", "F"] and not is_possible_trivial_body(res): - # We only strip method bodies if they don't assign to an attribute, as - # this may define an attribute which has an externally visible effect. - visitor = FindAttributeAssign() - for s in res: - s.accept(visitor) - if visitor.found: - can_strip = False - break - - if can_strip and is_coroutine: + if stack[-2:] == ["C", "F"]: + if is_possible_trivial_body(res): + can_strip = False + else: + # We only strip method bodies if they don't assign to an attribute, as + # this may define an attribute which has an externally visible effect. + visitor = FindAttributeAssign() + for s in res: + s.accept(visitor) + if visitor.found: + can_strip = False + break + + if can_strip and stack[-1] == "F" and is_coroutine: # Yields inside an async function affect the return type and should not # be stripped. yield_visitor = FindYield()