bpo-42747: Remove Py_TPFLAGS_HAVE_AM_SEND and make Py_TPFLAGS_HAVE_VERSION_TAG no-op (GH-27260)

* Remove code that checks Py_TPFLAGS_HAVE_VERSION_TAG
    
    The field is always present in the type struct, as explained
    in the added comment.

* Remove Py_TPFLAGS_HAVE_AM_SEND
    
    The flag is not needed, and since it was added in 3.10 it can be removed now.
This commit is contained in:
Petr Viktorin 2021-07-23 15:21:11 +02:00 committed by GitHub
parent 7d28a6eb90
commit a4760cc32d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 24 additions and 56 deletions

View File

@ -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 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 fields in the type object and its extension structures. Currently, it includes
the following bits: :const:`Py_TPFLAGS_HAVE_STACKLESS_EXTENSION`, the following bits: :const:`Py_TPFLAGS_HAVE_STACKLESS_EXTENSION`.
:const:`Py_TPFLAGS_HAVE_VERSION_TAG`.
**Inheritance:** **Inheritance:**
@ -1179,14 +1178,6 @@ and :c:type:`PyType_Type` effectively act as defaults.)
.. versionadded:: 3.9 .. 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 .. data:: Py_TPFLAGS_IMMUTABLETYPE
This bit is set for type objects that are immutable: type attributes cannot be set nor deleted. This bit is set for type objects that are immutable: type attributes cannot be set nor deleted.

View File

@ -368,18 +368,12 @@ given type object has a specified feature.
/* Objects behave like an unbound method */ /* Objects behave like an unbound method */
#define Py_TPFLAGS_METHOD_DESCRIPTOR (1UL << 17) #define Py_TPFLAGS_METHOD_DESCRIPTOR (1UL << 17)
/* Objects support type attribute cache */ /* Object has up-to-date type attribute cache */
#define Py_TPFLAGS_HAVE_VERSION_TAG (1UL << 18)
#define Py_TPFLAGS_VALID_VERSION_TAG (1UL << 19) #define Py_TPFLAGS_VALID_VERSION_TAG (1UL << 19)
/* Type is abstract and cannot be instantiated */ /* Type is abstract and cannot be instantiated */
#define Py_TPFLAGS_IS_ABSTRACT (1UL << 20) #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 // This undocumented flag gives certain built-ins their unique pattern-matching
// behavior, which allows a single positional subpattern to match against the // behavior, which allows a single positional subpattern to match against the
// subject itself (rather than a mapped attribute on it): // subject itself (rather than a mapped attribute on it):
@ -397,19 +391,23 @@ given type object has a specified feature.
#define Py_TPFLAGS_DEFAULT ( \ #define Py_TPFLAGS_DEFAULT ( \
Py_TPFLAGS_HAVE_STACKLESS_EXTENSION | \ Py_TPFLAGS_HAVE_STACKLESS_EXTENSION | \
Py_TPFLAGS_HAVE_VERSION_TAG | \
0) 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). */ * Python 3.0 transition). */
/* The following flag is kept for compatibility. Starting with 3.8, /* The following flags are kept for compatibility; in previous
* binary compatibility of C extensions across feature releases of * versions they indicated presence of newer tp_* fields on the
* Python is not supported anymore, except when using the stable ABI. * 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_FINALIZE (1UL << 0)
#define Py_TPFLAGS_HAVE_VERSION_TAG (1UL << 18)
/* /*

View File

@ -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.

View File

@ -1764,8 +1764,7 @@ static PyTypeObject FutureIterType = {
.tp_dealloc = (destructor)FutureIter_dealloc, .tp_dealloc = (destructor)FutureIter_dealloc,
.tp_as_async = &FutureIterType_as_async, .tp_as_async = &FutureIterType_as_async,
.tp_getattro = PyObject_GenericGetAttr, .tp_getattro = PyObject_GenericGetAttr,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Py_TPFLAGS_HAVE_AM_SEND,
.tp_traverse = (traverseproc)FutureIter_traverse, .tp_traverse = (traverseproc)FutureIter_traverse,
.tp_iter = PyObject_SelfIter, .tp_iter = PyObject_SelfIter,
.tp_iternext = (iternextfunc)FutureIter_iternext, .tp_iternext = (iternextfunc)FutureIter_iternext,

View File

@ -2804,9 +2804,7 @@ PyIter_Send(PyObject *iter, PyObject *arg, PyObject **result)
_Py_IDENTIFIER(send); _Py_IDENTIFIER(send);
assert(arg != NULL); assert(arg != NULL);
assert(result != NULL); assert(result != NULL);
if (PyType_HasFeature(Py_TYPE(iter), Py_TPFLAGS_HAVE_AM_SEND)) { if (Py_TYPE(iter)->tp_as_async && Py_TYPE(iter)->tp_as_async->am_send) {
assert (Py_TYPE(iter)->tp_as_async != NULL);
assert (Py_TYPE(iter)->tp_as_async->am_send != NULL);
PySendResult res = Py_TYPE(iter)->tp_as_async->am_send(iter, arg, result); PySendResult res = Py_TYPE(iter)->tp_as_async->am_send(iter, arg, result);
assert(_Py_CheckSlotResult(iter, "am_send", res != PYGEN_ERROR)); assert(_Py_CheckSlotResult(iter, "am_send", res != PYGEN_ERROR));
return res; return res;

View File

@ -782,8 +782,7 @@ PyTypeObject PyGen_Type = {
PyObject_GenericGetAttr, /* tp_getattro */ PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */ 0, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Py_TPFLAGS_HAVE_AM_SEND, /* tp_flags */
0, /* tp_doc */ 0, /* tp_doc */
(traverseproc)gen_traverse, /* tp_traverse */ (traverseproc)gen_traverse, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
@ -1029,8 +1028,7 @@ PyTypeObject PyCoro_Type = {
PyObject_GenericGetAttr, /* tp_getattro */ PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */ 0, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Py_TPFLAGS_HAVE_AM_SEND, /* tp_flags */
0, /* tp_doc */ 0, /* tp_doc */
(traverseproc)gen_traverse, /* tp_traverse */ (traverseproc)gen_traverse, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
@ -1415,8 +1413,7 @@ PyTypeObject PyAsyncGen_Type = {
PyObject_GenericGetAttr, /* tp_getattro */ PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */ 0, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Py_TPFLAGS_HAVE_AM_SEND, /* tp_flags */
0, /* tp_doc */ 0, /* tp_doc */
(traverseproc)async_gen_traverse, /* tp_traverse */ (traverseproc)async_gen_traverse, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */

View File

@ -324,10 +324,6 @@ PyType_Modified(PyTypeObject *type)
Invariants: 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, - before Py_TPFLAGS_VALID_VERSION_TAG can be set on a type,
it must first be set on all super types. 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 *mro_meth = NULL;
PyObject *type_mro_meth = NULL; PyObject *type_mro_meth = NULL;
if (!_PyType_HasFeature(type, Py_TPFLAGS_HAVE_VERSION_TAG))
return;
if (custom) { if (custom) {
mro_meth = lookup_maybe_method( mro_meth = lookup_maybe_method(
(PyObject *)type, &PyId_mro, &unbound); (PyObject *)type, &PyId_mro, &unbound);
@ -404,8 +397,7 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) {
assert(PyType_Check(b)); assert(PyType_Check(b));
cls = (PyTypeObject *)b; cls = (PyTypeObject *)b;
if (!_PyType_HasFeature(cls, Py_TPFLAGS_HAVE_VERSION_TAG) || if (!PyType_IsSubtype(type, cls)) {
!PyType_IsSubtype(type, cls)) {
goto clear; goto clear;
} }
} }
@ -413,8 +405,7 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) {
clear: clear:
Py_XDECREF(mro_meth); Py_XDECREF(mro_meth);
Py_XDECREF(type_mro_meth); Py_XDECREF(type_mro_meth);
type->tp_flags &= ~(Py_TPFLAGS_HAVE_VERSION_TAG| type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
Py_TPFLAGS_VALID_VERSION_TAG);
type->tp_version_tag = 0; /* 0 is not a 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)) if (_PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG))
return 1; return 1;
if (!_PyType_HasFeature(type, Py_TPFLAGS_HAVE_VERSION_TAG))
return 0;
if (!_PyType_HasFeature(type, Py_TPFLAGS_READY)) if (!_PyType_HasFeature(type, Py_TPFLAGS_READY))
return 0; return 0;
@ -5978,14 +5967,6 @@ type_ready_pre_checks(PyTypeObject *type)
_PyObject_ASSERT((PyObject *)type, type->tp_call != NULL); _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 /* Consistency checks for pattern matching
* Py_TPFLAGS_SEQUENCE and Py_TPFLAGS_MAPPING are mutually exclusive */ * Py_TPFLAGS_SEQUENCE and Py_TPFLAGS_MAPPING are mutually exclusive */
_PyObject_ASSERT((PyObject *)type, (type->tp_flags & COLLECTION_FLAGS) != COLLECTION_FLAGS); _PyObject_ASSERT((PyObject *)type, (type->tp_flags & COLLECTION_FLAGS) != COLLECTION_FLAGS);