python / python/mypy

Non-optional send types and the Generator.send() parameter

Open
#11,023 1 comment 6 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug topic-runtime-semantics
Dominant language
Python
Stars
20.6k
Forks
3.3k
PR merge metrics
PR metrics pending

Description

Bug Report

Python doesn’t allow you to send a non-None value to a just-started generator, but if the send type of a generator is not annotated Optional then .send(None) can’t be used.

You could just use next() at the start, but a situation can be created where Python and Mypy don’t agree on a type error. Pyright behaves similarly.

I’m not sure what the solution is here. This issue might require discussion.

To Reproduce
$ cat file1.py
from collections.abc import Generator

def g() -> Generator[int, int, None]:
    sent = 0
    while True:
        sent = yield sent

gen = g()
print(gen.send(0))  # <--
print(gen.send(1))
print(gen.send(2))
$ mypy --strict file1.py
Success: no issues found in 1 source file
$ python3 file1.py
Traceback (most recent call last):
  File "/Users/danpro/Desktop/fold/file1.py", line 10, in <module>
    print(gen.send(0))  # <--
TypeError: can't send non-None value to a just-started generator
$ 
$ 
$ cat file2.py
from collections.abc import Generator

def g() -> Generator[int, int, None]:
    sent = 0
    while True:
        sent = yield sent

gen = g()
print(gen.send(None))  # <--
print(gen.send(1))
print(gen.send(2))
$ mypy --strict file2.py
file2.py:10: error: Argument 1 to "send" of "Generator" has incompatible type "None"; expected "int"
Found 1 error in 1 file (checked 1 source file)
$ python3 file2.py
0
1
2
Expected Behavior

A TypeError should not occur at runtime when Mypy reports successful type checking.

Actual Behavior

A TypeError occurs even though Mypy reports successful type checking.

My Environment
  • Mypy version used: 0.910
  • Python version used: 3.9.6
  • Pyright version used: 1.1.163

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Generator.send() typing behavior described in the two file1.py and file2.py reproductions, comparing mypy's results with Python's runtime TypeError. Review how Generator's send type handles the initial None value and consider the interaction with the comparable Pyright behavior. Done means the type checker no longer accepts code that can immediately fail at runtime, with the intended behavior established for both examples.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
devtools
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.