Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add explanations of the yield statement to common_issues.rst Fixes #17996 #18422

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions docs/source/common_issues.rst
Original file line number Diff line number Diff line change
Expand Up @@ -846,3 +846,49 @@ or of potential subclasses.
# In the context of the subclass Bar, the Self return type promises
# that the return value will be Bar
reveal_type(Bar.constructor()) # note: Revealed type is "Bar"

Missing ``yield`` statement in generator functions
--------------------------------------------------

Python uses the ``yield`` statement to determine whether a function is a
generator function (https://peps.python.org/pep-0255/#specification-yield).

.. code-block:: python

from collections.abc import Generator, AsyncGenerator

async def async_gen() -> AsyncGenerator[int]:
yield 1

def gen() -> Generator[int]:
yield 1

async def async_func() -> int:
return 1

def func() -> int:
return 1

reveal_type(async_gen()) # AsyncGenerator[int, None]
reveal_type(gen()) # Generator[int, None, None]
reveal_type(async_func()) # Coroutine[Any, Any, int]
reveal_type(func()) # int

Functions containing ``yield`` statements will be regarded as Generator functions
by Python, and their return types are different from other functions.
Therefore, when using ``mypy`` to check types, we need to declare the return types
of such functions as Generator (or AsyncGenerator when the function is async).

A common mistake is that we declared the return type of a function as
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this is wrong: "Missing return statement" is not specific to Generator, that's just because the return type is non-None and the body s trivial.

A reasonable function can return a Generator or Iterator and contain no yield (this passes):

from collections.abc import Generator

def fn() -> Generator[int]:
    return (i for i in range(5))

On the other hand, missing return statement causes a diagnostic without Generator too (except for stub files):

def fn() -> int:
    ...  # E: Missing return statement  [empty-body]

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds reasonable, I'll re-write these lines.

Generator (AsyncGenerator) but did not use the ``yield`` statement in the function.
``mypy`` will consider that the return type (no return, or normal types) of this function
does not meet the expectation (generator type).

.. code-block:: python

from collections.abc import Generator

def gen() -> Generator[int]:
... # error: Missing return statement

This kind of mistake is common in unfinished functions (the function body is ``...``).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a sentence about overload here? overload bodies need to contain yield as well (see rejected #17435) . This would also close #17430 then.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I'll add.

Loading