diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index 004cecddfdb..b18e3852be3 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1098,8 +1098,7 @@ and :c:type:`PyType_Type` effectively act as defaults.) This is a bitmask of all the bits that pertain to the existence of certain fields in the type object and its extension structures. Currently, it includes - the following bits: :const:`Py_TPFLAGS_HAVE_STACKLESS_EXTENSION`, - :const:`Py_TPFLAGS_HAVE_VERSION_TAG`. + the following bits: :const:`Py_TPFLAGS_HAVE_STACKLESS_EXTENSION`. **Inheritance:** @@ -1179,14 +1178,6 @@ and :c:type:`PyType_Type` effectively act as defaults.) .. versionadded:: 3.9 - - .. data:: Py_TPFLAGS_HAVE_AM_SEND - - This bit is set when the :c:member:`~PyAsyncMethods.am_send` entry is present in the - :c:member:`~PyTypeObject.tp_as_async` slot of type structure. - - .. versionadded:: 3.10 - .. data:: Py_TPFLAGS_IMMUTABLETYPE This bit is set for type objects that are immutable: type attributes cannot be set nor deleted. diff --git a/Include/object.h b/Include/object.h index 109f535249c..9e6a8f4656a 100644 --- a/Include/object.h +++ b/Include/object.h @@ -368,18 +368,12 @@ given type object has a specified feature. /* Objects behave like an unbound method */ #define Py_TPFLAGS_METHOD_DESCRIPTOR (1UL << 17) -/* Objects support type attribute cache */ -#define Py_TPFLAGS_HAVE_VERSION_TAG (1UL << 18) +/* Object has up-to-date type attribute cache */ #define Py_TPFLAGS_VALID_VERSION_TAG (1UL << 19) /* Type is abstract and cannot be instantiated */ #define Py_TPFLAGS_IS_ABSTRACT (1UL << 20) -#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030A0000 -/* Type has am_send entry in tp_as_async slot */ -#define Py_TPFLAGS_HAVE_AM_SEND (1UL << 21) -#endif - // This undocumented flag gives certain built-ins their unique pattern-matching // behavior, which allows a single positional subpattern to match against the // subject itself (rather than a mapped attribute on it): @@ -397,19 +391,23 @@ given type object has a specified feature. #define Py_TPFLAGS_DEFAULT ( \ Py_TPFLAGS_HAVE_STACKLESS_EXTENSION | \ - Py_TPFLAGS_HAVE_VERSION_TAG | \ 0) -/* NOTE: The following flags reuse lower bits (removed as part of the +/* NOTE: Some of the following flags reuse lower bits (removed as part of the * Python 3.0 transition). */ -/* The following flag is kept for compatibility. Starting with 3.8, - * binary compatibility of C extensions across feature releases of - * Python is not supported anymore, except when using the stable ABI. +/* The following flags are kept for compatibility; in previous + * versions they indicated presence of newer tp_* fields on the + * type struct. + * Starting with 3.8, binary compatibility of C extensions across + * feature releases of Python is not supported anymore (except when + * using the stable ABI, in which all classes are created dynamically, + * using the interpreter's memory layout.) + * Note that older extensions using the stable ABI set these flags, + * so the bits must not be repurposed. */ - -/* Type structure has tp_finalize member (3.4) */ #define Py_TPFLAGS_HAVE_FINALIZE (1UL << 0) +#define Py_TPFLAGS_HAVE_VERSION_TAG (1UL << 18) /* diff --git a/Misc/NEWS.d/next/C API/2021-07-20-16-21-06.bpo-42747.rRxjUY.rst b/Misc/NEWS.d/next/C API/2021-07-20-16-21-06.bpo-42747.rRxjUY.rst new file mode 100644 index 00000000000..c7ac5a776e2 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2021-07-20-16-21-06.bpo-42747.rRxjUY.rst @@ -0,0 +1,4 @@ +The ``Py_TPFLAGS_HAVE_VERSION_TAG`` type flag now does nothing. The +``Py_TPFLAGS_HAVE_AM_SEND`` flag (which was added in 3.10) is removed. Both +were unnecessary because it is not possible to have type objects with the +relevant fields missing. diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index a4d5d4551e9..ecc73d1ca8b 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -1764,8 +1764,7 @@ static PyTypeObject FutureIterType = { .tp_dealloc = (destructor)FutureIter_dealloc, .tp_as_async = &FutureIterType_as_async, .tp_getattro = PyObject_GenericGetAttr, - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_HAVE_AM_SEND, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, .tp_traverse = (traverseproc)FutureIter_traverse, .tp_iter = PyObject_SelfIter, .tp_iternext = (iternextfunc)FutureIter_iternext, diff --git a/Objects/abstract.c b/Objects/abstract.c index f14a923c473..842c36780de 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2804,9 +2804,7 @@ PyIter_Send(PyObject *iter, PyObject *arg, PyObject **result) _Py_IDENTIFIER(send); assert(arg != NULL); assert(result != NULL); - if (PyType_HasFeature(Py_TYPE(iter), Py_TPFLAGS_HAVE_AM_SEND)) { - assert (Py_TYPE(iter)->tp_as_async != NULL); - assert (Py_TYPE(iter)->tp_as_async->am_send != NULL); + if (Py_TYPE(iter)->tp_as_async && Py_TYPE(iter)->tp_as_async->am_send) { PySendResult res = Py_TYPE(iter)->tp_as_async->am_send(iter, arg, result); assert(_Py_CheckSlotResult(iter, "am_send", res != PYGEN_ERROR)); return res; diff --git a/Objects/genobject.c b/Objects/genobject.c index 27fe15c2b9c..8cc965a51bb 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -782,8 +782,7 @@ PyTypeObject PyGen_Type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_HAVE_AM_SEND, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ (traverseproc)gen_traverse, /* tp_traverse */ 0, /* tp_clear */ @@ -1029,8 +1028,7 @@ PyTypeObject PyCoro_Type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_HAVE_AM_SEND, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ (traverseproc)gen_traverse, /* tp_traverse */ 0, /* tp_clear */ @@ -1415,8 +1413,7 @@ PyTypeObject PyAsyncGen_Type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_HAVE_AM_SEND, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ (traverseproc)async_gen_traverse, /* tp_traverse */ 0, /* tp_clear */ diff --git a/Objects/typeobject.c b/Objects/typeobject.c index badd7064fe3..42a9978ef30 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -324,10 +324,6 @@ PyType_Modified(PyTypeObject *type) Invariants: - - Py_TPFLAGS_VALID_VERSION_TAG is never set if - Py_TPFLAGS_HAVE_VERSION_TAG is not set (in case of a - bizarre MRO, see type_mro_modified()). - - before Py_TPFLAGS_VALID_VERSION_TAG can be set on a type, it must first be set on all super types. @@ -379,9 +375,6 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) { PyObject *mro_meth = NULL; PyObject *type_mro_meth = NULL; - if (!_PyType_HasFeature(type, Py_TPFLAGS_HAVE_VERSION_TAG)) - return; - if (custom) { mro_meth = lookup_maybe_method( (PyObject *)type, &PyId_mro, &unbound); @@ -404,8 +397,7 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) { assert(PyType_Check(b)); cls = (PyTypeObject *)b; - if (!_PyType_HasFeature(cls, Py_TPFLAGS_HAVE_VERSION_TAG) || - !PyType_IsSubtype(type, cls)) { + if (!PyType_IsSubtype(type, cls)) { goto clear; } } @@ -413,8 +405,7 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) { clear: Py_XDECREF(mro_meth); Py_XDECREF(type_mro_meth); - type->tp_flags &= ~(Py_TPFLAGS_HAVE_VERSION_TAG| - Py_TPFLAGS_VALID_VERSION_TAG); + type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG; type->tp_version_tag = 0; /* 0 is not a valid version tag */ } @@ -431,8 +422,6 @@ assign_version_tag(struct type_cache *cache, PyTypeObject *type) if (_PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG)) return 1; - if (!_PyType_HasFeature(type, Py_TPFLAGS_HAVE_VERSION_TAG)) - return 0; if (!_PyType_HasFeature(type, Py_TPFLAGS_READY)) return 0; @@ -5978,14 +5967,6 @@ type_ready_pre_checks(PyTypeObject *type) _PyObject_ASSERT((PyObject *)type, type->tp_call != NULL); } - /* Consistency check for Py_TPFLAGS_HAVE_AM_SEND - flag requires - * type->tp_as_async->am_send to be present. - */ - if (type->tp_flags & Py_TPFLAGS_HAVE_AM_SEND) { - _PyObject_ASSERT((PyObject *)type, type->tp_as_async != NULL); - _PyObject_ASSERT((PyObject *)type, type->tp_as_async->am_send != NULL); - } - /* Consistency checks for pattern matching * Py_TPFLAGS_SEQUENCE and Py_TPFLAGS_MAPPING are mutually exclusive */ _PyObject_ASSERT((PyObject *)type, (type->tp_flags & COLLECTION_FLAGS) != COLLECTION_FLAGS);