bpo-43683: Handle generator entry in bytecode (GH-25138)
* Handle check for sending None to starting generator and coroutine into bytecode.
* Document new bytecode and make it fail gracefully if mis-compiled.
diff --git a/Objects/genobject.c b/Objects/genobject.c
index 6998967..b02a558 100644
--- a/Objects/genobject.c
+++ b/Objects/genobject.c
@@ -176,27 +176,12 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult,
}
assert(_PyFrame_IsRunnable(f));
- if (f->f_lasti == -1) {
- if (arg && arg != Py_None) {
- const char *msg = "can't send non-None value to a "
- "just-started generator";
- if (PyCoro_CheckExact(gen)) {
- msg = NON_INIT_CORO_MSG;
- }
- else if (PyAsyncGen_CheckExact(gen)) {
- msg = "can't send non-None value to a "
- "just-started async generator";
- }
- PyErr_SetString(PyExc_TypeError, msg);
- return PYGEN_ERROR;
- }
- } else {
- /* Push arg onto the frame's value stack */
- result = arg ? arg : Py_None;
- Py_INCREF(result);
- gen->gi_frame->f_valuestack[gen->gi_frame->f_stackdepth] = result;
- gen->gi_frame->f_stackdepth++;
- }
+ assert(f->f_lasti >= 0 || ((unsigned char *)PyBytes_AS_STRING(f->f_code->co_code))[0] == GEN_START);
+ /* Push arg onto the frame's value stack */
+ result = arg ? arg : Py_None;
+ Py_INCREF(result);
+ gen->gi_frame->f_valuestack[gen->gi_frame->f_stackdepth] = result;
+ gen->gi_frame->f_stackdepth++;
/* Generators always return to their most recent caller, not
* necessarily their creator. */