Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-42747: Remove Py_TPFLAGS_HAVE_AM_SEND and make Py_TPFLAGS_HAVE_VERSION_TAG no-op #27260

Merged
merged 3 commits into from
Jul 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 1 addition & 10 deletions Doc/c-api/typeobj.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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:**

Expand Down Expand Up @@ -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.
Expand Down
26 changes: 12 additions & 14 deletions Include/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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)


/*
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Py_TPFLAGS_HAVE_AM_SEND flag (which was added in 3.10) is removed.

there aren't many users use it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there any users of it, they are using the 3.10 betas. Requiring that they remove the flag is fair game.

were unnecessary because it is not possible to have type objects with the
relevant fields missing.
3 changes: 1 addition & 2 deletions Modules/_asynciomodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 1 addition & 3 deletions Objects/abstract.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
9 changes: 3 additions & 6 deletions Objects/genobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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 */
Expand Down
23 changes: 2 additions & 21 deletions Objects/typeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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);
Expand All @@ -404,17 +397,15 @@ 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;
}
}
return;
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 */
}

Expand All @@ -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;

Expand Down Expand Up @@ -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);
Expand Down