Repository: cython/cython
Pull request: Swap all utility code types to be heap-types/type-specs
Closes #6633 (assuming that it doesn't break anything)

Problem statement:
[ENH?] Drop static types for Shared ABI utility code only?
### Describe your issue

I think there was a plan to eventually make all of our extension types heap types (although I'm struggling to find the issue right now...). If I remember correctly that was deferred because it wasn't possible to support all features all versions of Python that we support (I think the buffer protocol might have been an issue?).

However - the types in the Shared ABI (cyfunction, fused_function, generator, coroutine, etc.) use a narrower set of features and I think (but haven't tested) that they could work all heap types (`CYTHON_USE_TYPE_SPECS`) on all versions that we support now. Doing that would cut out a large chunk of code, and remove a one of the points of divergence where we have to create multiple shared ABI modules.

So the question is: is there any good reason not to do this, and to keep these in sync with `cdef class` types.

Hints from issue discussion:
I think this is an excellent idea. They are internal classes and thus do not suffer any of the interop/subclassing issues that user defined classes may have. Simplifying their setup seems an obvious win.

That's assuming that this works. CyFunction might be limited by its need to mimic PyCFunction. But even just cleaning up some of the types would bring some benefit.

Commit message: Hopefully fix am_send

Patch to review:
diff --git a/Cython/Utility/AsyncGen.c b/Cython/Utility/AsyncGen.c
index 19d4ebaf32b..c2bd7b013c6 100644
--- a/Cython/Utility/AsyncGen.c
+++ b/Cython/Utility/AsyncGen.c
@@ -297,9 +297,7 @@ static PyMemberDef __Pyx_async_gen_memberlist[] = {
     {"ag_await", T_OBJECT, offsetof(__pyx_CoroutineObject, yieldfrom), READONLY,
      PyDoc_STR("object being awaited on, or None")},
     {"__module__", T_OBJECT, offsetof(__pyx_CoroutineObject, gi_modulename), 0, 0},
-#if CYTHON_USE_TYPE_SPECS
     {"__weaklistoffset__", T_PYSSIZET, offsetof(__pyx_CoroutineObject, gi_weakreflist), READONLY, 0},
-#endif
     {0, 0, 0, 0, 0}      /* Sentinel */
 };
 
@@ -328,7 +326,6 @@ static PyMethodDef __Pyx_async_gen_methods[] = {
 };
 
 
-#if CYTHON_USE_TYPE_SPECS
 static PyType_Slot __pyx_AsyncGenType_slots[] = {
     {Py_tp_dealloc, (void *)__Pyx_Coroutine_dealloc},
     {Py_am_aiter, (void *)PyObject_SelfIter},
@@ -351,90 +348,6 @@ static PyType_Spec __pyx_AsyncGenType_spec = {
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
     __pyx_AsyncGenType_slots
 };
-#else /* CYTHON_USE_TYPE_SPECS */
-
-static __Pyx_PyAsyncMethodsStruct __Pyx_async_gen_as_async = {
-    0,                                          /* am_await */
-    PyObject_SelfIter,                          /* am_aiter */
-    (unaryfunc)__Pyx_async_gen_anext,           /* am_anext */
-    0,                                          /* am_send */
-};
-
-static PyTypeObject __pyx_AsyncGenType_type = {
-    PyVarObject_HEAD_INIT(0, 0)
-    "async_generator",                          /* tp_name */
-    sizeof(__pyx_PyAsyncGenObject),             /* tp_basicsize */
-    0,                                          /* tp_itemsize */
-    (destructor)__Pyx_Coroutine_dealloc,        /* tp_dealloc */
-    0,                                          /* tp_vectorcall_offset */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-    __Pyx_SlotTpAsAsync(__Pyx_async_gen_as_async),    /* tp_as_async */
-    (reprfunc)__Pyx_async_gen_repr,             /* tp_repr */
-    0,                                          /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    0,                                          /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call */
-    0,                                          /* tp_str */
-    0,                                          /* tp_getattro */
-    0,                                          /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
-        Py_TPFLAGS_HAVE_FINALIZE,               /* tp_flags */
-    0,                                          /* tp_doc */
-    (traverseproc)__Pyx_async_gen_traverse,     /* tp_traverse */
-    0,                                          /* tp_clear */
-    0,                                          /*tp_richcompare*/
-    offsetof(__pyx_CoroutineObject, gi_weakreflist), /* tp_weaklistoffset */
-    0,                                          /* tp_iter */
-    0,                                          /* tp_iternext */
-    __Pyx_async_gen_methods,                          /* tp_methods */
-    __Pyx_async_gen_memberlist,                       /* tp_members */
-    __Pyx_async_gen_getsetlist,                       /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    0,                                          /* tp_init */
-    0,                                          /* tp_alloc */
-    0,                                          /* tp_new */
-    0,                                          /* tp_free */
-    0,                                          /* tp_is_gc */
-    0,                                          /* tp_bases */
-    0,                                          /* tp_mro */
-    0,                                          /* tp_cache */
-    0,                                          /* tp_subclasses */
-    0,                                          /* tp_weaklist */
-#if CYTHON_USE_TP_FINALIZE
-    0,                                  /*tp_del*/
-#else
-    __Pyx_Coroutine_del,                /*tp_del*/
-#endif
-    0,                                          /* tp_version_tag */
-#if CYTHON_USE_TP_FINALIZE
-    __Pyx_Coroutine_del,                        /* tp_finalize */
-#else
-    0,                                          /* tp_finalize */
-#endif
-#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
-    0,                                          /*tp_vectorcall*/
-#endif
-#if __PYX_NEED_TP_PRINT_SLOT
-    0,                                          /*tp_print*/
-#endif
-#if PY_VERSION_HEX >= 0x030C0000
-    0,                                          /*tp_watched*/
-#endif
-#if PY_VERSION_HEX >= 0x030d00A4
-    0,                                          /*tp_versions_used*/
-#endif
-#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000
-    0,                                          /*tp_pypy_flags*/
-#endif
-};
-#endif  /* CYTHON_USE_TYPE_SPECS */
 
 
 static int
@@ -615,7 +528,6 @@ static PyMethodDef __Pyx_async_gen_asend_methods[] = {
 };
 
 
-#if CYTHON_USE_TYPE_SPECS
 static PyType_Slot __pyx__PyAsyncGenASendType_slots[] = {
     {Py_tp_dealloc, (void *)__Pyx_async_gen_asend_dealloc},
     {Py_am_await, (void *)PyObject_SelfIter},
@@ -633,82 +545,6 @@ static PyType_Spec __pyx__PyAsyncGenASendType_spec = {
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
     __pyx__PyAsyncGenASendType_slots
 };
-#else /* CYTHON_USE_TYPE_SPECS */
-
-static __Pyx_PyAsyncMethodsStruct __Pyx_async_gen_asend_as_async = {
-    PyObject_SelfIter,                          /* am_await */
-    0,                                          /* am_aiter */
-    0,                                          /* am_anext */
-    0,                                          /* am_send */
-};
-
-static PyTypeObject __pyx__PyAsyncGenASendType_type = {
-    PyVarObject_HEAD_INIT(0, 0)
-    "async_generator_asend",                    /* tp_name */
-    sizeof(__pyx_PyAsyncGenASend),                    /* tp_basicsize */
-    0,                                          /* tp_itemsize */
-    /* methods */
-    (destructor)__Pyx_async_gen_asend_dealloc,        /* tp_dealloc */
-    0,                                          /* tp_vectorcall_offset */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-    __Pyx_SlotTpAsAsync(__Pyx_async_gen_asend_as_async),   /* tp_as_async */
-    0,                                          /* tp_repr */
-    0,                                          /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    0,                                          /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call */
-    0,                                          /* tp_str */
-    0,                                          /* tp_getattro */
-    0,                                          /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
-    0,                                          /* tp_doc */
-    (traverseproc)__Pyx_async_gen_asend_traverse,  /* tp_traverse */
-    0,                                          /* tp_clear */
-    0,                                          /*tp_richcompare*/
-    0,                                          /* tp_weaklistoffset */
-    PyObject_SelfIter,                          /* tp_iter */
-    (iternextfunc)__Pyx_async_gen_asend_iternext,     /* tp_iternext */
-    __Pyx_async_gen_asend_methods,                    /* tp_methods */
-    0,                                          /* tp_members */
-    0,                                          /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    0,                                          /* tp_init */
-    0,                                          /* tp_alloc */
-    0,                                          /* tp_new */
-    0,                                          /* tp_free */
-    0,                                          /* tp_is_gc */
-    0,                                          /* tp_bases */
-    0,                                          /* tp_mro */
-    0,                                          /* tp_cache */
-    0,                                          /* tp_subclasses */
-    0,                                          /* tp_weaklist */
-    0,                                          /* tp_del */
-    0,                                          /* tp_version_tag */
-    0,                                          /* tp_finalize */
-#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
-    0,                                          /*tp_vectorcall*/
-#endif
-#if __PYX_NEED_TP_PRINT_SLOT
-    0,                                          /*tp_print*/
-#endif
-#if PY_VERSION_HEX >= 0x030C0000
-    0,                                          /*tp_watched*/
-#endif
-#if PY_VERSION_HEX >= 0x030d00A4
-    0,                                          /*tp_versions_used*/
-#endif
-#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000
-    0,                                          /*tp_pypy_flags*/
-#endif
-};
-#endif /* CYTHON_USE_TYPE_SPECS */
 
 
 static PyObject *
@@ -775,7 +611,6 @@ __Pyx_async_gen_wrapped_val_traverse(__pyx__PyAsyncGenWrappedValue *o,
 }
 
 
-#if CYTHON_USE_TYPE_SPECS
 static PyType_Slot __pyx__PyAsyncGenWrappedValueType_slots[] = {
     {Py_tp_dealloc, (void *)__Pyx_async_gen_wrapped_val_dealloc},
     {Py_tp_traverse, (void *)__Pyx_async_gen_wrapped_val_traverse},
@@ -789,75 +624,6 @@ static PyType_Spec __pyx__PyAsyncGenWrappedValueType_spec = {
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
     __pyx__PyAsyncGenWrappedValueType_slots
 };
-#else /* CYTHON_USE_TYPE_SPECS */
-
-static PyTypeObject __pyx__PyAsyncGenWrappedValueType_type = {
-    PyVarObject_HEAD_INIT(0, 0)
-    "async_generator_wrapped_value",            /* tp_name */
-    sizeof(__pyx__PyAsyncGenWrappedValue),            /* tp_basicsize */
-    0,                                          /* tp_itemsize */
-    /* methods */
-    (destructor)__Pyx_async_gen_wrapped_val_dealloc,  /* tp_dealloc */
-    0,                                          /* tp_vectorcall_offset */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-    0,                                          /* tp_as_async */
-    0,                                          /* tp_repr */
-    0,                                          /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    0,                                          /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call */
-    0,                                          /* tp_str */
-    0,                                          /* tp_getattro */
-    0,                                          /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
-    0,                                          /* tp_doc */
-    (traverseproc)__Pyx_async_gen_wrapped_val_traverse,    /* tp_traverse */
-    0,                                          /* tp_clear */
-    0,                                          /* tp_richcompare */
-    0,                                          /* tp_weaklistoffset */
-    0,                                          /* tp_iter */
-    0,                                          /* tp_iternext */
-    0,                                          /* tp_methods */
-    0,                                          /* tp_members */
-    0,                                          /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    0,                                          /* tp_init */
-    0,                                          /* tp_alloc */
-    0,                                          /* tp_new */
-    0,                                          /* tp_free */
-    0,                                          /* tp_is_gc */
-    0,                                          /* tp_bases */
-    0,                                          /* tp_mro */
-    0,                                          /* tp_cache */
-    0,                                          /* tp_subclasses */
-    0,                                          /* tp_weaklist */
-    0,                                          /* tp_del */
-    0,                                          /* tp_version_tag */
-    0,                                          /* tp_finalize */
-#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
-    0,                                          /*tp_vectorcall*/
-#endif
-#if __PYX_NEED_TP_PRINT_SLOT
-    0,                                          /*tp_print*/
-#endif
-#if PY_VERSION_HEX >= 0x030C0000
-    0,                                          /*tp_watched*/
-#endif
-#if PY_VERSION_HEX >= 0x030d00A4
-    0,                                          /*tp_versions_used*/
-#endif
-#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000
-    0,                                          /*tp_pypy_flags*/
-#endif
-};
-#endif /* CYTHON_USE_TYPE_SPECS */
 
 
 static PyObject *
@@ -1103,7 +869,6 @@ static PyMethodDef __Pyx_async_gen_athrow_methods[] = {
 };
 
 
-#if CYTHON_USE_TYPE_SPECS
 static PyType_Slot __pyx__PyAsyncGenAThrowType_slots[] = {
     {Py_tp_dealloc, (void *)__Pyx_async_gen_athrow_dealloc},
     {Py_am_await, (void *)PyObject_SelfIter},
@@ -1122,81 +887,6 @@ static PyType_Spec __pyx__PyAsyncGenAThrowType_spec = {
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
     __pyx__PyAsyncGenAThrowType_slots
 };
-#else /* CYTHON_USE_TYPE_SPECS */
-
-static __Pyx_PyAsyncMethodsStruct __Pyx_async_gen_athrow_as_async = {
-    PyObject_SelfIter,                          /* am_await */
-    0,                                          /* am_aiter */
-    0,                                          /* am_anext */
-    0,                                          /* am_send */
-};
-
-static PyTypeObject __pyx__PyAsyncGenAThrowType_type = {
-    PyVarObject_HEAD_INIT(0, 0)
-    "async_generator_athrow",                   /* tp_name */
-    sizeof(__pyx_PyAsyncGenAThrow),                   /* tp_basicsize */
-    0,                                          /* tp_itemsize */
-    (destructor)__Pyx_async_gen_athrow_dealloc,       /* tp_dealloc */
-    0,                                          /* tp_vectorcall_offset */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-    __Pyx_SlotTpAsAsync(__Pyx_async_gen_athrow_as_async),   /* tp_as_async */
-    0,                                          /* tp_repr */
-    0,                                          /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    0,                                          /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call */
-    0,                                          /* tp_str */
-    0,                                          /* tp_getattro */
-    0,                                          /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
-    0,                                          /* tp_doc */
-    (traverseproc)__Pyx_async_gen_athrow_traverse,    /* tp_traverse */
-    0,                                          /* tp_clear */
-    0,                                          /*tp_richcompare*/
-    0,                                          /* tp_weaklistoffset */
-    PyObject_SelfIter,                          /* tp_iter */
-    (iternextfunc)__Pyx_async_gen_athrow_iternext,    /* tp_iternext */
-    __Pyx_async_gen_athrow_methods,                   /* tp_methods */
-    0,                                          /* tp_members */
-    0,                                          /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    0,                                          /* tp_init */
-    0,                                          /* tp_alloc */
-    0,                                          /* tp_new */
-    0,                                          /* tp_free */
-    0,                                          /* tp_is_gc */
-    0,                                          /* tp_bases */
-    0,                                          /* tp_mro */
-    0,                                          /* tp_cache */
-    0,                                          /* tp_subclasses */
-    0,                                          /* tp_weaklist */
-    0,                                          /* tp_del */
-    0,                                          /* tp_version_tag */
-    0,                                          /* tp_finalize */
-#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
-    0,                                          /*tp_vectorcall*/
-#endif
-#if __PYX_NEED_TP_PRINT_SLOT
-    0,                                          /*tp_print*/
-#endif
-#if PY_VERSION_HEX >= 0x030C0000
-    0,                                          /*tp_watched*/
-#endif
-#if PY_VERSION_HEX >= 0x030d00A4
-    0,                                          /*tp_versions_used*/
-#endif
-#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000
-    0,                                          /*tp_pypy_flags*/
-#endif
-};
-#endif /* CYTHON_USE_TYPE_SPECS */
 
 
 static PyObject *
@@ -1221,41 +911,19 @@ __Pyx_async_gen_athrow_new(__pyx_PyAsyncGenObject *gen, PyObject *args)
 
 static int __pyx_AsyncGen_init(PyObject *module) {
     $modulestatetype_cname *mstate = __Pyx_PyModule_GetState(module);
-#if CYTHON_USE_TYPE_SPECS
     mstate->__pyx_AsyncGenType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_AsyncGenType_spec, NULL);
-#else
-    CYTHON_MAYBE_UNUSED_VAR(module);
-    // on Windows, C-API functions can't be used in slots statically
-    __pyx_AsyncGenType_type.tp_getattro = PyObject_GenericGetAttr;
-    mstate->__pyx_AsyncGenType = __Pyx_FetchCommonType(&__pyx_AsyncGenType_type);
-#endif
     if (unlikely(!mstate->__pyx_AsyncGenType))
         return -1;
 
-#if CYTHON_USE_TYPE_SPECS
     mstate->__pyx__PyAsyncGenAThrowType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx__PyAsyncGenAThrowType_spec, NULL);
-#else
-    __pyx__PyAsyncGenAThrowType_type.tp_getattro = PyObject_GenericGetAttr;
-    mstate->__pyx__PyAsyncGenAThrowType = __Pyx_FetchCommonType(&__pyx__PyAsyncGenAThrowType_type);
-#endif
     if (unlikely(!mstate->__pyx__PyAsyncGenAThrowType))
         return -1;
 
-#if CYTHON_USE_TYPE_SPECS
     mstate->__pyx__PyAsyncGenWrappedValueType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx__PyAsyncGenWrappedValueType_spec, NULL);
-#else
-    __pyx__PyAsyncGenWrappedValueType_type.tp_getattro = PyObject_GenericGetAttr;
-    mstate->__pyx__PyAsyncGenWrappedValueType = __Pyx_FetchCommonType(&__pyx__PyAsyncGenWrappedValueType_type);
-#endif
     if (unlikely(!mstate->__pyx__PyAsyncGenWrappedValueType))
         return -1;
 
-#if CYTHON_USE_TYPE_SPECS
     mstate->__pyx__PyAsyncGenASendType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx__PyAsyncGenASendType_spec, NULL);
-#else
-    __pyx__PyAsyncGenASendType_type.tp_getattro = PyObject_GenericGetAttr;
-    mstate->__pyx__PyAsyncGenASendType = __Pyx_FetchCommonType(&__pyx__PyAsyncGenASendType_type);
-#endif
     if (unlikely(!mstate->__pyx__PyAsyncGenASendType))
         return -1;
 
diff --git a/Cython/Utility/CommonStructures.c b/Cython/Utility/CommonStructures.c
index 8287b041b83..f3cfd8d2af5 100644
--- a/Cython/Utility/CommonStructures.c
+++ b/Cython/Utility/CommonStructures.c
@@ -10,11 +10,7 @@ static PyObject *__Pyx_FetchSharedCythonABIModule(void) {
 
 /////////////// FetchCommonType.proto ///////////////
 
-#if !CYTHON_USE_TYPE_SPECS
-static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type);
-#else
 static PyTypeObject* __Pyx_FetchCommonTypeFromSpec(PyObject *module, PyType_Spec *spec, PyObject *bases);
-#endif
 
 /////////////// FetchCommonType ///////////////
 //@requires:ExtensionTypes.c::FixUpExtensionType
@@ -39,49 +35,6 @@ static int __Pyx_VerifyCachedType(PyObject *cached_type,
     return 0;
 }
 
-#if !CYTHON_USE_TYPE_SPECS
-static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type) {
-    PyObject* abi_module;
-    const char* object_name;
-    PyTypeObject *cached_type = NULL;
-
-    abi_module = __Pyx_FetchSharedCythonABIModule();
-    if (!abi_module) return NULL;
-    // get the final part of the object name (after the last dot)
-    object_name = strrchr(type->tp_name, '.');
-    object_name = object_name ? object_name+1 : type->tp_name;
-    cached_type = (PyTypeObject*) PyObject_GetAttrString(abi_module, object_name);
-    if (cached_type) {
-        if (__Pyx_VerifyCachedType(
-              (PyObject *)cached_type,
-              object_name,
-              cached_type->tp_basicsize,
-              type->tp_basicsize) < 0) {
-            goto bad;
-        }
-        goto done;
-    }
-
-    if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad;
-    PyErr_Clear();
-    if (PyType_Ready(type) < 0) goto bad;
-    if (PyObject_SetAttrString(abi_module, object_name, (PyObject *)type) < 0)
-        goto bad;
-    Py_INCREF(type);
-    cached_type = type;
-
-done:
-    Py_DECREF(abi_module);
-    // NOTE: always returns owned reference, or NULL on error
-    return cached_type;
-
-bad:
-    Py_XDECREF(cached_type);
-    cached_type = NULL;
-    goto done;
-}
-#else
-
 static PyTypeObject *__Pyx_FetchCommonTypeFromSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) {
     PyObject *abi_module, *cached_type = NULL;
     // get the final part of the object name (after the last dot)
@@ -135,5 +88,4 @@ static PyTypeObject *__Pyx_FetchCommonTypeFromSpec(PyObject *module, PyType_Spec
     cached_type = NULL;
     goto done;
 }
-#endif
 
diff --git a/Cython/Utility/Coroutine.c b/Cython/Utility/Coroutine.c
index 4a8970f9fb3..911d9781442 100644
--- a/Cython/Utility/Coroutine.c
+++ b/Cython/Utility/Coroutine.c
@@ -1416,7 +1416,7 @@ static void __Pyx_Coroutine_dealloc(PyObject *self) {
     __Pyx_PyHeapTypeObject_GC_Del(gen);
 }
 
-#if !(CYTHON_USE_TYPE_SPECS && !CYTHON_USE_TP_FINALIZE)
+#if CYTHON_USE_TP_FINALIZE
 static void __Pyx_Coroutine_del(PyObject *self) {
     PyObject *error_type, *error_value, *error_traceback;
     __pyx_CoroutineObject *gen = (__pyx_CoroutineObject *) self;
@@ -1427,12 +1427,6 @@ static void __Pyx_Coroutine_del(PyObject *self) {
         return;
     }
 
-#if !CYTHON_USE_TP_FINALIZE
-    // Temporarily resurrect the object.
-    assert(self->ob_refcnt == 0);
-    __Pyx_SET_REFCNT(self, 1);
-#endif
-
     __Pyx_PyThreadState_assign
 
     // Save the current exception, if any.
@@ -1482,45 +1476,6 @@ static void __Pyx_Coroutine_del(PyObject *self) {
 
     // Restore the saved exception.
     __Pyx_ErrRestore(error_type, error_value, error_traceback);
-
-#if !CYTHON_USE_TP_FINALIZE
-    // Undo the temporary resurrection; can't use DECREF here, it would
-    // cause a recursive call.
-    assert(Py_REFCNT(self) > 0);
-    if (likely(--self->ob_refcnt == 0)) {
-        // this is the normal path out
-        return;
-    }
-
-    // close() resurrected it!  Make it look like the original Py_DECREF
-    // never happened.
-    {
-#if !CYTHON_COMPILING_IN_LIMITED_API
-        Py_ssize_t refcnt = Py_REFCNT(self);
-        _Py_NewReference(self);
-        __Pyx_SET_REFCNT(self, refcnt);
-#else
-        #error __Pyx_Coroutine_del with Limited API and without CYTHON_USE_TP_FINALIZE should never be compiled
-#endif
-    }
-#if CYTHON_COMPILING_IN_CPYTHON
-    assert(PyType_IS_GC(Py_TYPE(self)) &&
-           _Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED);
-
-    // If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
-    // we need to undo that.
-    _Py_DEC_REFTOTAL;
-#endif
-    // If Py_TRACE_REFS, _Py_NewReference re-added self to the object
-    // chain, so no more to do there.
-    // If COUNT_ALLOCS, the original decref bumped tp_frees, and
-    // _Py_NewReference bumped tp_allocs:  both of those need to be
-    // undone.
-#ifdef COUNT_ALLOCS
-    --Py_TYPE(self)->tp_frees;
-    --Py_TYPE(self)->tp_allocs;
-#endif
-#endif
 }
 #endif
 
@@ -1726,7 +1681,7 @@ static PyObject *__Pyx_CoroutineAwait_Send(__pyx_CoroutineAwaitObject *self, PyO
     return __Pyx_Coroutine_Send(self->coroutine, value);
 }
 
-#if __PYX_HAS_PY_AM_SEND || !CYTHON_USE_TYPE_SPECS
+#if __PYX_HAS_PY_AM_SEND
 static __Pyx_PySendResult __Pyx_CoroutineAwait_AmSend(PyObject *self, PyObject *value, PyObject **retval) {
     return __Pyx_Coroutine_AmSend(((__pyx_CoroutineAwaitObject*)self)->coroutine, value, retval);
 }
@@ -1802,7 +1757,6 @@ static PyMethodDef __pyx_CoroutineAwait_methods[] = {
     {0, 0, 0, 0}
 };
 
-#if CYTHON_USE_TYPE_SPECS
 static PyType_Slot __pyx_CoroutineAwaitType_slots[] = {
     {Py_tp_dealloc, (void *)__Pyx_CoroutineAwait_dealloc},
     {Py_tp_traverse, (void *)__Pyx_CoroutineAwait_traverse},
@@ -1826,84 +1780,6 @@ static PyType_Spec __pyx_CoroutineAwaitType_spec = {
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
     __pyx_CoroutineAwaitType_slots
 };
-#else /* CYTHON_USE_TYPE_SPECS */
-static __Pyx_PyAsyncMethodsStruct __pyx_CoroutineAwait_as_async = {
-    0,                              /*am_await*/
-    0,                              /*am_aiter*/
-    0,                              /*am_anext*/
-    __Pyx_CoroutineAwait_AmSend,    /*am_send*/
-};
-
-static PyTypeObject __pyx_CoroutineAwaitType_type = {
-    PyVarObject_HEAD_INIT(0, 0)
-    __PYX_TYPE_MODULE_PREFIX "coroutine_wrapper", /*tp_name*/
-    sizeof(__pyx_CoroutineAwaitObject), /*tp_basicsize*/
-    0,                                  /*tp_itemsize*/
-    (destructor) __Pyx_CoroutineAwait_dealloc,/*tp_dealloc*/
-    0,                                  /*tp_print*/
-    0,                                  /*tp_getattr*/
-    0,                                  /*tp_setattr*/
-    __Pyx_SlotTpAsAsync(__pyx_CoroutineAwait_as_async),    /*tp_as_async*/
-    0,                                  /*tp_repr*/
-    0,                                  /*tp_as_number*/
-    0,                                  /*tp_as_sequence*/
-    0,                                  /*tp_as_mapping*/
-    0,                                  /*tp_hash*/
-    0,                                  /*tp_call*/
-    0,                                  /*tp_str*/
-    0,                                  /*tp_getattro*/
-    0,                                  /*tp_setattro*/
-    0,                                  /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | __Pyx_TPFLAGS_HAVE_AM_SEND, /*tp_flags*/
-    PyDoc_STR("A wrapper object implementing __await__ for coroutines."), /*tp_doc*/
-    (traverseproc) __Pyx_CoroutineAwait_traverse,   /*tp_traverse*/
-    (inquiry) __Pyx_CoroutineAwait_clear,           /*tp_clear*/
-    0,                                  /*tp_richcompare*/
-    0,                                  /*tp_weaklistoffset*/
-    __Pyx_CoroutineAwait_self,          /*tp_iter*/
-    (iternextfunc) __Pyx_CoroutineAwait_Next, /*tp_iternext*/
-    __pyx_CoroutineAwait_methods,       /*tp_methods*/
-    0                         ,         /*tp_members*/
-    0                      ,            /*tp_getset*/
-    0,                                  /*tp_base*/
-    0,                                  /*tp_dict*/
-    0,                                  /*tp_descr_get*/
-    0,                                  /*tp_descr_set*/
-    0,                                  /*tp_dictoffset*/
-    0,                                  /*tp_init*/
-    0,                                  /*tp_alloc*/
-#if !CYTHON_COMPILING_IN_PYPY
-    __Pyx_CoroutineAwait_no_new,        /*tp_new*/
-#else
-    0,                                  /*tp_new*/
-#endif
-    0,                                  /*tp_free*/
-    0,                                  /*tp_is_gc*/
-    0,                                  /*tp_bases*/
-    0,                                  /*tp_mro*/
-    0,                                  /*tp_cache*/
-    0,                                  /*tp_subclasses*/
-    0,                                  /*tp_weaklist*/
-    0,                                  /*tp_del*/
-    0,                                  /*tp_version_tag*/
-    0,                                  /*tp_finalize*/
-#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
-    0,                                  /*tp_vectorcall*/
-#endif
-#if __PYX_NEED_TP_PRINT_SLOT
-    0,                                  /*tp_print*/
-#endif
-#if PY_VERSION_HEX >= 0x030C0000
-    0,                                  /*tp_watched*/
-#endif
-#if PY_VERSION_HEX >= 0x030d00A4
-    0,                                          /*tp_versions_used*/
-#endif
-#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000
-    0,                                          /*tp_pypy_flags*/
-#endif
-};
-#endif  /* CYTHON_USE_TYPE_SPECS */
 
 static CYTHON_INLINE PyObject *__Pyx__Coroutine_await(PyObject *coroutine) {
     __pyx_CoroutineAwaitObject *await = PyObject_GC_New(__pyx_CoroutineAwaitObject, CGLOBAL(__pyx_CoroutineAwaitType));
@@ -1936,9 +1812,7 @@ static PyMemberDef __pyx_Coroutine_memberlist[] = {
      PyDoc_STR("object being awaited, or None")},
     {"cr_code", T_OBJECT, offsetof(__pyx_CoroutineObject, gi_code), READONLY, NULL},
     {"__module__", T_OBJECT, offsetof(__pyx_CoroutineObject, gi_modulename), 0, 0},
-#if CYTHON_USE_TYPE_SPECS
     {"__weaklistoffset__", T_PYSSIZET, offsetof(__pyx_CoroutineObject, gi_weakreflist), READONLY, 0},
-#endif
     {0, 0, 0, 0, 0}
 };
 
@@ -1954,7 +1828,6 @@ static PyGetSetDef __pyx_Coroutine_getsets[] = {
     {0, 0, 0, 0, 0}
 };
 
-#if CYTHON_USE_TYPE_SPECS
 static PyType_Slot __pyx_CoroutineType_slots[] = {
     {Py_tp_dealloc, (void *)__Pyx_Coroutine_dealloc},
     {Py_am_await, (void *)&__Pyx_Coroutine_await},
@@ -1979,102 +1852,13 @@ static PyType_Spec __pyx_CoroutineType_spec = {
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
     __pyx_CoroutineType_slots
 };
-#else /* CYTHON_USE_TYPE_SPECS */
-
-static __Pyx_PyAsyncMethodsStruct __pyx_Coroutine_as_async = {
-    __Pyx_Coroutine_await,  /*am_await*/
-    0,                      /*am_aiter*/
-    0,                      /*am_anext*/
-    __Pyx_Coroutine_AmSend, /*am_send*/
-};
-
-static PyTypeObject __pyx_CoroutineType_type = {
-    PyVarObject_HEAD_INIT(0, 0)
-    __PYX_TYPE_MODULE_PREFIX "coroutine", /*tp_name*/
-    sizeof(__pyx_CoroutineObject),      /*tp_basicsize*/
-    0,                                  /*tp_itemsize*/
-    (destructor) __Pyx_Coroutine_dealloc,/*tp_dealloc*/
-    0,                                  /*tp_print*/
-    0,                                  /*tp_getattr*/
-    0,                                  /*tp_setattr*/
-    __Pyx_SlotTpAsAsync(__pyx_Coroutine_as_async),       /*tp_as_async*/
-    0,                                  /*tp_repr*/
-    0,                                  /*tp_as_number*/
-    0,                                  /*tp_as_sequence*/
-    0,                                  /*tp_as_mapping*/
-    0,                                  /*tp_hash*/
-    0,                                  /*tp_call*/
-    0,                                  /*tp_str*/
-    0,                                  /*tp_getattro*/
-    0,                                  /*tp_setattro*/
-    0,                                  /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE | __Pyx_TPFLAGS_HAVE_AM_SEND, /*tp_flags*/
-    0,                                  /*tp_doc*/
-    (traverseproc) __Pyx_Coroutine_traverse,   /*tp_traverse*/
-    0,                                  /*tp_clear*/
-    0,                                  /*tp_richcompare*/
-    offsetof(__pyx_CoroutineObject, gi_weakreflist), /*tp_weaklistoffset*/
-    // no tp_iter() as iterator is only available through __await__()
-    0,                                  /*tp_iter*/
-    0,                                  /*tp_iternext*/
-    __pyx_Coroutine_methods,            /*tp_methods*/
-    __pyx_Coroutine_memberlist,         /*tp_members*/
-    __pyx_Coroutine_getsets,            /*tp_getset*/
-    0,                                  /*tp_base*/
-    0,                                  /*tp_dict*/
-    0,                                  /*tp_descr_get*/
-    0,                                  /*tp_descr_set*/
-    0,                                  /*tp_dictoffset*/
-    0,                                  /*tp_init*/
-    0,                                  /*tp_alloc*/
-    0,                                  /*tp_new*/
-    0,                                  /*tp_free*/
-    0,                                  /*tp_is_gc*/
-    0,                                  /*tp_bases*/
-    0,                                  /*tp_mro*/
-    0,                                  /*tp_cache*/
-    0,                                  /*tp_subclasses*/
-    0,                                  /*tp_weaklist*/
-#if CYTHON_USE_TP_FINALIZE
-    0,                                  /*tp_del*/
-#else
-    __Pyx_Coroutine_del,                /*tp_del*/
-#endif
-    0,                                  /*tp_version_tag*/
-#if CYTHON_USE_TP_FINALIZE
-    __Pyx_Coroutine_del,                /*tp_finalize*/
-#else
-    0,                                  /*tp_finalize*/
-#endif
-#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
-    0,                                  /*tp_vectorcall*/
-#endif
-#if __PYX_NEED_TP_PRINT_SLOT
-    0,                                  /*tp_print*/
-#endif
-#if PY_VERSION_HEX >= 0x030C0000
-    0,                                  /*tp_watched*/
-#endif
-#if PY_VERSION_HEX >= 0x030d00A4
-    0,                                          /*tp_versions_used*/
-#endif
-#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000
-    0,                                          /*tp_pypy_flags*/
-#endif
-};
-#endif /* CYTHON_USE_TYPE_SPECS */
 
 static int __pyx_Coroutine_init(PyObject *module) {
     $modulestatetype_cname *mstate;
     CYTHON_MAYBE_UNUSED_VAR(module);
     // on Windows, C-API functions can't be used in slots statically
     mstate = __Pyx_PyModule_GetState(module);
-#if CYTHON_USE_TYPE_SPECS
     mstate->__pyx_CoroutineType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_CoroutineType_spec, NULL);
-#else
-    __pyx_CoroutineType_type.tp_getattro = PyObject_GenericGetAttr;
-    mstate->__pyx_CoroutineType = __Pyx_FetchCommonType(&__pyx_CoroutineType_type);
-#endif
     if (unlikely(!mstate->__pyx_CoroutineType))
         return -1;
 #ifdef __Pyx_IterableCoroutine_USED
@@ -2082,11 +1866,7 @@ static int __pyx_Coroutine_init(PyObject *module) {
         return -1;
 #endif
 
-#if CYTHON_USE_TYPE_SPECS
     mstate->__pyx_CoroutineAwaitType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_CoroutineAwaitType_spec, NULL);
-#else
-    mstate->__pyx_CoroutineAwaitType = __Pyx_FetchCommonType(&__pyx_CoroutineAwaitType_type);
-#endif
     if (unlikely(!mstate->__pyx_CoroutineAwaitType))
         return -1;
     return 0;
@@ -2111,7 +1891,6 @@ static int __pyx_IterableCoroutine_init(PyObject *module);/*proto*/
 //@requires: CommonStructures.c::FetchCommonType
 //@substitute: naming
 
-#if CYTHON_USE_TYPE_SPECS
 static PyType_Slot __pyx_IterableCoroutineType_slots[] = {
     {Py_tp_dealloc, (void *)__Pyx_Coroutine_dealloc},
     {Py_am_await, (void *)&__Pyx_Coroutine_await},
@@ -2138,88 +1917,11 @@ static PyType_Spec __pyx_IterableCoroutineType_spec = {
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
     __pyx_IterableCoroutineType_slots
 };
-#else /* CYTHON_USE_TYPE_SPECS */
-
-static PyTypeObject __pyx_IterableCoroutineType_type = {
-    PyVarObject_HEAD_INIT(0, 0)
-    __PYX_TYPE_MODULE_PREFIX "iterable_coroutine", /*tp_name*/
-    sizeof(__pyx_CoroutineObject),      /*tp_basicsize*/
-    0,                                  /*tp_itemsize*/
-    (destructor) __Pyx_Coroutine_dealloc,/*tp_dealloc*/
-    0,                                  /*tp_print*/
-    0,                                  /*tp_getattr*/
-    0,                                  /*tp_setattr*/
-    __Pyx_SlotTpAsAsync(__pyx_Coroutine_as_async),  /*tp_as_async*/
-    0,                                  /*tp_repr*/
-    0,                                  /*tp_as_number*/
-    0,                                  /*tp_as_sequence*/
-    0,                                  /*tp_as_mapping*/
-    0,                                  /*tp_hash*/
-    0,                                  /*tp_call*/
-    0,                                  /*tp_str*/
-    0,                                  /*tp_getattro*/
-    0,                                  /*tp_setattro*/
-    0,                                  /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE | __Pyx_TPFLAGS_HAVE_AM_SEND, /*tp_flags*/
-    0,                                  /*tp_doc*/
-    (traverseproc) __Pyx_Coroutine_traverse,   /*tp_traverse*/
-    0,                                  /*tp_clear*/
-    0,                                  /*tp_richcompare*/
-    offsetof(__pyx_CoroutineObject, gi_weakreflist), /*tp_weaklistoffset*/
-    // enable iteration for legacy support of asyncio yield-from protocol
-    __Pyx_Coroutine_await,              /*tp_iter*/
-    (iternextfunc) __Pyx_Generator_Next, /*tp_iternext*/
-    __pyx_Coroutine_methods,            /*tp_methods*/
-    __pyx_Coroutine_memberlist,         /*tp_members*/
-    __pyx_Coroutine_getsets,            /*tp_getset*/
-    0,                                  /*tp_base*/
-    0,                                  /*tp_dict*/
-    0,                                  /*tp_descr_get*/
-    0,                                  /*tp_descr_set*/
-    0,                                  /*tp_dictoffset*/
-    0,                                  /*tp_init*/
-    0,                                  /*tp_alloc*/
-    0,                                  /*tp_new*/
-    0,                                  /*tp_free*/
-    0,                                  /*tp_is_gc*/
-    0,                                  /*tp_bases*/
-    0,                                  /*tp_mro*/
-    0,                                  /*tp_cache*/
-    0,                                  /*tp_subclasses*/
-    0,                                  /*tp_weaklist*/
-    0,                                  /*tp_del*/
-    0,                                  /*tp_version_tag*/
-#if !CYTHON_COMPILING_IN_PYPY
-    __Pyx_Coroutine_del,                /*tp_finalize*/
-#endif
-#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
-    0,                                  /*tp_vectorcall*/
-#endif
-#if __PYX_NEED_TP_PRINT_SLOT
-    0,                                  /*tp_print*/
-#endif
-#if PY_VERSION_HEX >= 0x030C0000
-    0,                                  /*tp_watched*/
-#endif
-#if PY_VERSION_HEX >= 0x030d00A4
-    0,                                          /*tp_versions_used*/
-#endif
-#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000
-    0,                                          /*tp_pypy_flags*/
-#endif
-};
-#endif /* CYTHON_USE_TYPE_SPECS */
 
 
 static int __pyx_IterableCoroutine_init(PyObject *module) {
     $modulestatetype_cname *mstate = __Pyx_PyModule_GetState(module);
-#if CYTHON_USE_TYPE_SPECS
     mstate->__pyx_IterableCoroutineType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_IterableCoroutineType_spec, NULL);
-#else
-    CYTHON_UNUSED_VAR(module);
-    __pyx_IterableCoroutineType_type.tp_getattro = PyObject_GenericGetAttr;
-    mstate->__pyx_IterableCoroutineType = __Pyx_FetchCommonType(&__pyx_IterableCoroutineType_type);
-#endif
     if (unlikely(!mstate->__pyx_IterableCoroutineType))
         return -1;
     return 0;
@@ -2246,9 +1948,7 @@ static PyMemberDef __pyx_Generator_memberlist[] = {
      PyDoc_STR("object being iterated by 'yield from', or None")},
     {"gi_code", T_OBJECT, offsetof(__pyx_CoroutineObject, gi_code), READONLY, NULL},
     {"__module__", T_OBJECT, offsetof(__pyx_CoroutineObject, gi_modulename), 0, 0},
-#if CYTHON_USE_TYPE_SPECS
     {"__weaklistoffset__", T_PYSSIZET, offsetof(__pyx_CoroutineObject, gi_weakreflist), READONLY, 0},
-#endif
     {0, 0, 0, 0, 0}
 };
 
@@ -2262,7 +1962,6 @@ static PyGetSetDef __pyx_Generator_getsets[] = {
     {0, 0, 0, 0, 0}
 };
 
-#if CYTHON_USE_TYPE_SPECS
 static PyType_Slot __pyx_GeneratorType_slots[] = {
     {Py_tp_dealloc, (void *)__Pyx_Coroutine_dealloc},
     {Py_tp_traverse, (void *)__Pyx_Coroutine_traverse},
@@ -2288,99 +1987,10 @@ static PyType_Spec __pyx_GeneratorType_spec = {
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
     __pyx_GeneratorType_slots
 };
-#else /* CYTHON_USE_TYPE_SPECS */
-static __Pyx_PyAsyncMethodsStruct __pyx_Generator_as_async = {
-    0,                          /*am_await*/
-    0,                          /*am_aiter*/
-    0,                          /*am_anext*/
-    __Pyx_Coroutine_AmSend,     /*am_send*/
-};
-
-static PyTypeObject __pyx_GeneratorType_type = {
-    PyVarObject_HEAD_INIT(0, 0)
-    __PYX_TYPE_MODULE_PREFIX "generator", /*tp_name*/
-    sizeof(__pyx_CoroutineObject),      /*tp_basicsize*/
-    0,                                  /*tp_itemsize*/
-    (destructor) __Pyx_Coroutine_dealloc,/*tp_dealloc*/
-    0,                                  /*tp_print*/
-    0,                                  /*tp_getattr*/
-    0,                                  /*tp_setattr*/
-    __Pyx_SlotTpAsAsync(__pyx_Generator_as_async),   /*tp_as_async*/
-    0,                                  /*tp_repr*/
-    0,                                  /*tp_as_number*/
-    0,                                  /*tp_as_sequence*/
-    0,                                  /*tp_as_mapping*/
-    0,                                  /*tp_hash*/
-    0,                                  /*tp_call*/
-    0,                                  /*tp_str*/
-    0,                                  /*tp_getattro*/
-    0,                                  /*tp_setattro*/
-    0,                                  /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE | __Pyx_TPFLAGS_HAVE_AM_SEND, /*tp_flags*/
-    0,                                  /*tp_doc*/
-    (traverseproc) __Pyx_Coroutine_traverse,   /*tp_traverse*/
-    0,                                  /*tp_clear*/
-    0,                                  /*tp_richcompare*/
-    offsetof(__pyx_CoroutineObject, gi_weakreflist), /*tp_weaklistoffset*/
-    0,                                  /*tp_iter*/
-    (iternextfunc) __Pyx_Generator_Next, /*tp_iternext*/
-    __pyx_Generator_methods,            /*tp_methods*/
-    __pyx_Generator_memberlist,         /*tp_members*/
-    __pyx_Generator_getsets,            /*tp_getset*/
-    0,                                  /*tp_base*/
-    0,                                  /*tp_dict*/
-    0,                                  /*tp_descr_get*/
-    0,                                  /*tp_descr_set*/
-    0,                                  /*tp_dictoffset*/
-    0,                                  /*tp_init*/
-    0,                                  /*tp_alloc*/
-    0,                                  /*tp_new*/
-    0,                                  /*tp_free*/
-    0,                                  /*tp_is_gc*/
-    0,                                  /*tp_bases*/
-    0,                                  /*tp_mro*/
-    0,                                  /*tp_cache*/
-    0,                                  /*tp_subclasses*/
-    0,                                  /*tp_weaklist*/
-#if CYTHON_USE_TP_FINALIZE
-    0,                                  /*tp_del*/
-#else
-    __Pyx_Coroutine_del,                /*tp_del*/
-#endif
-    0,                                  /*tp_version_tag*/
-#if CYTHON_USE_TP_FINALIZE
-    __Pyx_Coroutine_del,                /*tp_finalize*/
-#else
-    0,                                  /*tp_finalize*/
-#endif
-#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
-    0,                                  /*tp_vectorcall*/
-#endif
-#if __PYX_NEED_TP_PRINT_SLOT
-    0,                                  /*tp_print*/
-#endif
-#if PY_VERSION_HEX >= 0x030C0000
-    0,                                  /*tp_watched*/
-#endif
-#if PY_VERSION_HEX >= 0x030d00A4
-    0,                                          /*tp_versions_used*/
-#endif
-#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000
-    0,                                          /*tp_pypy_flags*/
-#endif
-};
-#endif /* CYTHON_USE_TYPE_SPECS */
 
 static int __pyx_Generator_init(PyObject *module) {
     $modulestatetype_cname *mstate = __Pyx_PyModule_GetState(module);
-#if CYTHON_USE_TYPE_SPECS
     mstate->__pyx_GeneratorType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_GeneratorType_spec, NULL);
-#else
-    // on Windows, C-API functions can't be used in slots statically
-    __pyx_GeneratorType_type.tp_getattro = PyObject_GenericGetAttr;
-    __pyx_GeneratorType_type.tp_iter = PyObject_SelfIter;
-    mstate->__pyx_GeneratorType = __Pyx_FetchCommonType(&__pyx_GeneratorType_type);
-#endif
     if (unlikely(!mstate->__pyx_GeneratorType)) {
         return -1;
     }
diff --git a/Cython/Utility/CythonFunction.c b/Cython/Utility/CythonFunction.c
index 7552ee40899..4112cbace27 100644
--- a/Cython/Utility/CythonFunction.c
+++ b/Cython/Utility/CythonFunction.c
@@ -659,7 +659,6 @@ static PyMemberDef __pyx_CyFunction_members[] = {
 #if !CYTHON_COMPILING_IN_LIMITED_API
     {"__module__", T_OBJECT, offsetof(PyCFunctionObject, m_module), 0, 0},
 #endif
-#if CYTHON_USE_TYPE_SPECS
     {"__dictoffset__", T_PYSSIZET, offsetof(__pyx_CyFunctionObject, func_dict), READONLY, 0},
 #if CYTHON_METH_FASTCALL
 #if CYTHON_BACKPORT_VECTORCALL || CYTHON_COMPILING_IN_LIMITED_API
@@ -667,7 +666,6 @@ static PyMemberDef __pyx_CyFunction_members[] = {
 #else
     {"__vectorcalloffset__", T_PYSSIZET, offsetof(PyCFunctionObject, vectorcall), READONLY, 0},
 #endif
-#endif
 #if CYTHON_COMPILING_IN_LIMITED_API
     {"__weaklistoffset__", T_PYSSIZET, offsetof(__pyx_CyFunctionObject, func_weakreflist), READONLY, 0},
 #else
@@ -1196,7 +1194,6 @@ static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS_METHOD(PyObject
 }
 #endif
 
-#if CYTHON_USE_TYPE_SPECS
 static PyType_Slot __pyx_CyFunctionType_slots[] = {
     {Py_tp_dealloc, (void *)__Pyx_CyFunction_dealloc},
     {Py_tp_repr, (void *)__Pyx_CyFunction_repr},
@@ -1227,95 +1224,10 @@ static PyType_Spec __pyx_CyFunctionType_spec = {
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /*tp_flags*/
     __pyx_CyFunctionType_slots
 };
-#else /* CYTHON_USE_TYPE_SPECS */
-
-static PyTypeObject __pyx_CyFunctionType_type = {
-    PyVarObject_HEAD_INIT(0, 0)
-    __PYX_TYPE_MODULE_PREFIX "cython_function_or_method",  /*tp_name*/
-    sizeof(__pyx_CyFunctionObject),   /*tp_basicsize*/
-    0,                                  /*tp_itemsize*/
-    (destructor) __Pyx_CyFunction_dealloc, /*tp_dealloc*/
-#if !CYTHON_METH_FASTCALL
-    0,                                  /*tp_print*/
-#elif CYTHON_BACKPORT_VECTORCALL
-    (printfunc)offsetof(__pyx_CyFunctionObject, func_vectorcall), /*tp_vectorcall_offset backported into tp_print*/
-#else
-    offsetof(PyCFunctionObject, vectorcall), /*tp_vectorcall_offset*/
-#endif
-    0,                                  /*tp_getattr*/
-    0,                                  /*tp_setattr*/
-    0,                                  /*tp_as_async*/
-    (reprfunc) __Pyx_CyFunction_repr,   /*tp_repr*/
-    0,                                  /*tp_as_number*/
-    0,                                  /*tp_as_sequence*/
-    0,                                  /*tp_as_mapping*/
-    0,                                  /*tp_hash*/
-    __Pyx_CyFunction_CallAsMethod,      /*tp_call*/
-    0,                                  /*tp_str*/
-    0,                                  /*tp_getattro*/
-    0,                                  /*tp_setattro*/
-    0,                                  /*tp_as_buffer*/
-#ifdef Py_TPFLAGS_METHOD_DESCRIPTOR
-    Py_TPFLAGS_METHOD_DESCRIPTOR |
-#endif
-#if defined(_Py_TPFLAGS_HAVE_VECTORCALL) && CYTHON_METH_FASTCALL
-    _Py_TPFLAGS_HAVE_VECTORCALL |
-#endif
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /*tp_flags*/
-    0,                                  /*tp_doc*/
-    (traverseproc) __Pyx_CyFunction_traverse,   /*tp_traverse*/
-    (inquiry) __Pyx_CyFunction_clear,   /*tp_clear*/
-    0,                                  /*tp_richcompare*/
-    offsetof(PyCFunctionObject, m_weakreflist),         /*tp_weaklistoffset*/
-    0,                                  /*tp_iter*/
-    0,                                  /*tp_iternext*/
-    __pyx_CyFunction_methods,           /*tp_methods*/
-    __pyx_CyFunction_members,           /*tp_members*/
-    __pyx_CyFunction_getsets,           /*tp_getset*/
-    0,                                  /*tp_base*/
-    0,                                  /*tp_dict*/
-    __Pyx_PyMethod_New,                 /*tp_descr_get*/
-    0,                                  /*tp_descr_set*/
-    offsetof(__pyx_CyFunctionObject, func_dict),/*tp_dictoffset*/
-    0,                                  /*tp_init*/
-    0,                                  /*tp_alloc*/
-    0,                                  /*tp_new*/
-    0,                                  /*tp_free*/
-    0,                                  /*tp_is_gc*/
-    0,                                  /*tp_bases*/
-    0,                                  /*tp_mro*/
-    0,                                  /*tp_cache*/
-    0,                                  /*tp_subclasses*/
-    0,                                  /*tp_weaklist*/
-    0,                                  /*tp_del*/
-    0,                                  /*tp_version_tag*/
-    0,                                  /*tp_finalize*/
-#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
-    0,                                  /*tp_vectorcall*/
-#endif
-#if __PYX_NEED_TP_PRINT_SLOT
-    0,                                  /*tp_print*/
-#endif
-#if PY_VERSION_HEX >= 0x030C0000
-    0,                                  /*tp_watched*/
-#endif
-#if PY_VERSION_HEX >= 0x030d00A4
-    0,                                          /*tp_versions_used*/
-#endif
-#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000
-    0,                                          /*tp_pypy_flags*/
-#endif
-};
-#endif  /* CYTHON_USE_TYPE_SPECS */
-
 
 static int __pyx_CyFunction_init(PyObject *module) {
     $modulestatetype_cname *mstate = __Pyx_PyModule_GetState(module);
-#if CYTHON_USE_TYPE_SPECS
     mstate->__pyx_CyFunctionType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_CyFunctionType_spec, NULL);
-#else
-    mstate->__pyx_CyFunctionType = __Pyx_FetchCommonType(&__pyx_CyFunctionType_type);
-#endif
     if (unlikely(mstate->__pyx_CyFunctionType == NULL)) {
         return -1;
     }
@@ -1753,7 +1665,6 @@ static PyGetSetDef __pyx_FusedFunction_getsets[] = {
     {0, 0, 0, 0, 0}
 };
 
-#if CYTHON_USE_TYPE_SPECS
 static PyType_Slot __pyx_FusedFunctionType_slots[] = {
     {Py_tp_dealloc, (void *)__pyx_FusedFunction_dealloc},
     {Py_tp_call, (void *)__pyx_FusedFunction_call},
@@ -1774,96 +1685,14 @@ static PyType_Spec __pyx_FusedFunctionType_spec = {
     __pyx_FusedFunctionType_slots
 };
 
-#else  /* !CYTHON_USE_TYPE_SPECS */
-
-static PyMappingMethods __pyx_FusedFunction_mapping_methods = {
-    0,
-    (binaryfunc) __pyx_FusedFunction_getitem,
-    0,
-};
-
-static PyTypeObject __pyx_FusedFunctionType_type = {
-    PyVarObject_HEAD_INIT(0, 0)
-    __PYX_TYPE_MODULE_PREFIX "fused_cython_function",  /*tp_name*/
-    sizeof(__pyx_FusedFunctionObject), /*tp_basicsize*/
-    0,                                  /*tp_itemsize*/
-    (destructor) __pyx_FusedFunction_dealloc, /*tp_dealloc*/
-    0,                                  /*tp_print*/
-    0,                                  /*tp_getattr*/
-    0,                                  /*tp_setattr*/
-    0,                                  /*tp_as_async*/
-    0,                                  /*tp_repr*/
-    0,                                  /*tp_as_number*/
-    0,                                  /*tp_as_sequence*/
-    &__pyx_FusedFunction_mapping_methods, /*tp_as_mapping*/
-    0,                                  /*tp_hash*/
-    (ternaryfunc) __pyx_FusedFunction_call, /*tp_call*/
-    0,                                  /*tp_str*/
-    0,                                  /*tp_getattro*/
-    0,                                  /*tp_setattro*/
-    0,                                  /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /*tp_flags*/
-    0,                                  /*tp_doc*/
-    (traverseproc) __pyx_FusedFunction_traverse,   /*tp_traverse*/
-    (inquiry) __pyx_FusedFunction_clear,/*tp_clear*/
-    0,                                  /*tp_richcompare*/
-    0,                                  /*tp_weaklistoffset*/
-    0,                                  /*tp_iter*/
-    0,                                  /*tp_iternext*/
-    0,                                  /*tp_methods*/
-    __pyx_FusedFunction_members,        /*tp_members*/
-    __pyx_FusedFunction_getsets,           /*tp_getset*/
-    // NOTE: tp_base may be changed later during module initialisation when importing CyFunction across modules.
-    &__pyx_CyFunctionType_type,         /*tp_base*/
-    0,                                  /*tp_dict*/
-    __pyx_FusedFunction_descr_get,      /*tp_descr_get*/
-    0,                                  /*tp_descr_set*/
-    0,                                  /*tp_dictoffset*/
-    0,                                  /*tp_init*/
-    0,                                  /*tp_alloc*/
-    0,                                  /*tp_new*/
-    0,                                  /*tp_free*/
-    0,                                  /*tp_is_gc*/
-    0,                                  /*tp_bases*/
-    0,                                  /*tp_mro*/
-    0,                                  /*tp_cache*/
-    0,                                  /*tp_subclasses*/
-    0,                                  /*tp_weaklist*/
-    0,                                  /*tp_del*/
-    0,                                  /*tp_version_tag*/
-    0,                                  /*tp_finalize*/
-#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
-    0,                                  /*tp_vectorcall*/
-#endif
-#if __PYX_NEED_TP_PRINT_SLOT
-    0,                                  /*tp_print*/
-#endif
-#if PY_VERSION_HEX >= 0x030C0000
-    0,                                  /*tp_watched*/
-#endif
-#if PY_VERSION_HEX >= 0x030d00A4
-    0,                                          /*tp_versions_used*/
-#endif
-#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000
-    0,                                          /*tp_pypy_flags*/
-#endif
-};
-#endif
-
 static int __pyx_FusedFunction_init(PyObject *module) {
     $modulestatetype_cname *mstate = __Pyx_PyModule_GetState(module);
-#if CYTHON_USE_TYPE_SPECS
     PyObject *bases = PyTuple_Pack(1, mstate->__pyx_CyFunctionType);
     if (unlikely(!bases)) {
         return -1;
     }
     mstate->__pyx_FusedFunctionType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_FusedFunctionType_spec, bases);
     Py_DECREF(bases);
-#else
-    // Set base from __Pyx_FetchCommonTypeFromSpec, in case it's different from the local static value.
-    __pyx_FusedFunctionType_type.tp_base = mstate->__pyx_CyFunctionType;
-    mstate->__pyx_FusedFunctionType = __Pyx_FetchCommonType(&__pyx_FusedFunctionType_type);
-#endif
     if (unlikely(mstate->__pyx_FusedFunctionType == NULL)) {
         return -1;
     }
diff --git a/Cython/Utility/ExtensionTypes.c b/Cython/Utility/ExtensionTypes.c
index e28efc8b7bd..757ac77030e 100644
--- a/Cython/Utility/ExtensionTypes.c
+++ b/Cython/Utility/ExtensionTypes.c
@@ -1,14 +1,11 @@
 /////////////// FixUpExtensionType.proto ///////////////
 
-#if CYTHON_USE_TYPE_SPECS
-static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject *type); /*proto*/
-#endif
+static CYTHON_INLINE int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject *type); /*proto*/
 
 /////////////// FixUpExtensionType ///////////////
 //@requires:ModuleSetupCode.c::IncludeStructmemberH
 //@requires:StringTools.c::IncludeStringH
 
-#if CYTHON_USE_TYPE_SPECS
 static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject *type) {
 #if PY_VERSION_HEX > 0x030900B1 || CYTHON_COMPILING_IN_LIMITED_API
     CYTHON_UNUSED_VAR(spec);
@@ -89,7 +86,6 @@ static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject
 #endif
     return 0;
 }
-#endif
 
 
 /////////////// ValidateBasesTuple.proto ///////////////
diff --git a/Cython/Utility/ModuleSetupCode.c b/Cython/Utility/ModuleSetupCode.c
index 93d7e3c0acd..f73ccd778bd 100644
--- a/Cython/Utility/ModuleSetupCode.c
+++ b/Cython/Utility/ModuleSetupCode.c
@@ -1187,8 +1187,8 @@ static CYTHON_INLINE int __Pyx_PyDict_GetItemRef(PyObject *dict, PyObject *key,
   #define __Pyx_pyiter_sendfunc sendfunc
 #endif
 
-// "Py_am_send" requires Py3.10 when using type specs.
-#define __PYX_HAS_PY_AM_SEND  (!CYTHON_USE_TYPE_SPECS || CYTHON_USE_AM_SEND && __PYX_LIMITED_VERSION_HEX >= 0x030A0000)
+// "Py_am_send" requires Py3.10 when using type specs (which utility code types do).
+#define __PYX_HAS_PY_AM_SEND  CYTHON_USE_AM_SEND && __PYX_LIMITED_VERSION_HEX >= 0x030A0000
 
 #if __PYX_LIMITED_VERSION_HEX >= 0x030A0000
     #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods


Code review comments:
diff_hunk: @@ -1187,8 +1187,8 @@ static CYTHON_INLINE int __Pyx_PyDict_GetItemRef(PyObject *dict, PyObject *key,
   #define __Pyx_pyiter_sendfunc sendfunc
 #endif
 
-// "Py_am_send" requires Py3.10 when using type specs.
-#define __PYX_HAS_PY_AM_SEND  (!CYTHON_USE_TYPE_SPECS || CYTHON_USE_AM_SEND && __PYX_LIMITED_VERSION_HEX >= 0x030A0000)
+// "Py_am_send" requires Py3.10 when using type specs (which utility code types do).
+#define __PYX_HAS_PY_AM_SEND  CYTHON_USE_AM_SEND && __PYX_LIMITED_VERSION_HEX >= 0x030A0000
path: Cython/Utility/ModuleSetupCode.c
text: @user1:
Should we keep the static type implementation of coroutines for Py3.[89] then?

@author:
I think it can be made to with with heaptypes (outside the limited API). It's probably just a case of rewriting `tp_as_async` after creation so it points back to a statically allocated version. I'll give that a go in the near future

diff_hunk: @@ -351,90 +348,6 @@ static PyType_Spec __pyx_AsyncGenType_spec = {
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
path: Cython/Utility/AsyncGen.c
text: @author:
I  wonder if I should add `Py_TPFLAGS_IMMUTABLETYPE` to all of these? That's probably the main visible difference between the heap-type and static-type version, and think they genuinely should be immutable.

@user1:
Try it. Sounds right.