bpo-32388: Remove cross-version binary compatibility requirement in tp_flags (GH-4944)

It is now allowed to add new fields at the end of the PyTypeObject struct without having to allocate a dedicated compatibility flag in tp_flags.

This will reduce the risk of running out of bits in the 32-bit tp_flags value.
This commit is contained in:
Antoine Pitrou 2019-05-29 22:12:38 +02:00 committed by GitHub
parent 43fdbd2729
commit ada319bb6d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 52 additions and 51 deletions

View File

@ -1099,6 +1099,11 @@ and :c:type:`PyType_Type` effectively act as defaults.)
.. versionadded:: 3.4 .. versionadded:: 3.4
.. deprecated:: 3.8
This flag isn't necessary anymore, as the interpreter assumes the
:c:member:`~PyTypeObject.tp_finalize` slot is always present in the
type structure.
.. c:member:: const char* PyTypeObject.tp_doc .. c:member:: const char* PyTypeObject.tp_doc

View File

@ -1265,6 +1265,15 @@ Changes in the C API
(Contributed by Zackery Spytz in :issue:`33407`.) (Contributed by Zackery Spytz in :issue:`33407`.)
* The interpreter does not pretend to support binary compatibility of
extension types accross feature releases, anymore. A :c:type:`PyTypeObject`
exported by a third-party extension module is supposed to have all the
slots expected in the current Python version, including
:c:member:`~PyTypeObject.tp_finalize` (:const:`Py_TPFLAGS_HAVE_FINALIZE`
is not checked anymore before reading :c:member:`~PyTypeObject.tp_finalize`).
(Contributed by Antoine Pitrou in :issue:`32388`.)
CPython bytecode changes CPython bytecode changes
------------------------ ------------------------

View File

@ -263,17 +263,14 @@ PyAPI_FUNC(void) Py_ReprLeave(PyObject *);
#define Py_PRINT_RAW 1 /* No string quotes etc. */ #define Py_PRINT_RAW 1 /* No string quotes etc. */
/* /*
`Type flags (tp_flags) Type flags (tp_flags)
These flags are used to extend the type structure in a backwards-compatible These flags are used to change expected features and behavior for a
fashion. Extensions can use the flags to indicate (and test) when a given particular type.
type structure contains a new feature. The Python core will use these when
introducing new functionality between major revisions (to avoid mid-version
changes in the PYTHON_API_VERSION).
Arbitration of the flag bit positions will need to be coordinated among Arbitration of the flag bit positions will need to be coordinated among
all extension writers who publicly release their extensions (this will all extension writers who publicly release their extensions (this will
be fewer than you might expect!).. be fewer than you might expect!).
Most flags were removed as of Python 3.0 to make room for new flags. (Some Most flags were removed as of Python 3.0 to make room for new flags. (Some
flags are not for backwards compatibility but to indicate the presence of an flags are not for backwards compatibility but to indicate the presence of an
@ -302,7 +299,7 @@ given type object has a specified feature.
/* Set while the type is being 'readied', to prevent recursive ready calls */ /* Set while the type is being 'readied', to prevent recursive ready calls */
#define Py_TPFLAGS_READYING (1UL << 13) #define Py_TPFLAGS_READYING (1UL << 13)
/* Objects support garbage collection (see objimp.h) */ /* Objects support garbage collection (see objimpl.h) */
#define Py_TPFLAGS_HAVE_GC (1UL << 14) #define Py_TPFLAGS_HAVE_GC (1UL << 14)
/* These two bits are preserved for Stackless Python, next after this is 17 */ /* These two bits are preserved for Stackless Python, next after this is 17 */
@ -340,6 +337,11 @@ given type object has a specified feature.
/* NOTE: The following flags reuse lower bits (removed as part of the /* NOTE: 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,
* binary compatibility of C extensions accross feature releases of
* Python is not supported anymore, except when using the stable ABI.
*/
/* Type structure has tp_finalize member (3.4) */ /* Type structure has tp_finalize member (3.4) */
#define Py_TPFLAGS_HAVE_FINALIZE (1UL << 0) #define Py_TPFLAGS_HAVE_FINALIZE (1UL << 0)

View File

@ -0,0 +1 @@
Remove cross-version binary compatibility requirement in tp_flags.

View File

@ -1430,8 +1430,7 @@ static PyTypeObject FutureType = {
.tp_dealloc = FutureObj_dealloc, .tp_dealloc = FutureObj_dealloc,
.tp_as_async = &FutureType_as_async, .tp_as_async = &FutureType_as_async,
.tp_repr = (reprfunc)FutureObj_repr, .tp_repr = (reprfunc)FutureObj_repr,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
| Py_TPFLAGS_HAVE_FINALIZE,
.tp_doc = _asyncio_Future___init____doc__, .tp_doc = _asyncio_Future___init____doc__,
.tp_traverse = (traverseproc)FutureObj_traverse, .tp_traverse = (traverseproc)FutureObj_traverse,
.tp_clear = (inquiry)FutureObj_clear, .tp_clear = (inquiry)FutureObj_clear,
@ -2461,8 +2460,7 @@ static PyTypeObject TaskType = {
.tp_dealloc = TaskObj_dealloc, .tp_dealloc = TaskObj_dealloc,
.tp_as_async = &FutureType_as_async, .tp_as_async = &FutureType_as_async,
.tp_repr = (reprfunc)FutureObj_repr, .tp_repr = (reprfunc)FutureObj_repr,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
| Py_TPFLAGS_HAVE_FINALIZE,
.tp_doc = _asyncio_Task___init____doc__, .tp_doc = _asyncio_Task___init____doc__,
.tp_traverse = (traverseproc)TaskObj_traverse, .tp_traverse = (traverseproc)TaskObj_traverse,
.tp_clear = (inquiry)TaskObj_clear, .tp_clear = (inquiry)TaskObj_clear,

View File

@ -2342,8 +2342,7 @@ PyTypeObject PyBufferedIOBase_Type = {
0, /*tp_getattro*/ 0, /*tp_getattro*/
0, /*tp_setattro*/ 0, /*tp_setattro*/
0, /*tp_as_buffer*/ 0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
| Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
bufferediobase_doc, /* tp_doc */ bufferediobase_doc, /* tp_doc */
0, /* tp_traverse */ 0, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
@ -2434,7 +2433,7 @@ PyTypeObject PyBufferedReader_Type = {
0, /*tp_setattro*/ 0, /*tp_setattro*/
0, /*tp_as_buffer*/ 0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
| Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
_io_BufferedReader___init____doc__, /* tp_doc */ _io_BufferedReader___init____doc__, /* tp_doc */
(traverseproc)buffered_traverse, /* tp_traverse */ (traverseproc)buffered_traverse, /* tp_traverse */
(inquiry)buffered_clear, /* tp_clear */ (inquiry)buffered_clear, /* tp_clear */
@ -2520,7 +2519,7 @@ PyTypeObject PyBufferedWriter_Type = {
0, /*tp_setattro*/ 0, /*tp_setattro*/
0, /*tp_as_buffer*/ 0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
| Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
_io_BufferedWriter___init____doc__, /* tp_doc */ _io_BufferedWriter___init____doc__, /* tp_doc */
(traverseproc)buffered_traverse, /* tp_traverse */ (traverseproc)buffered_traverse, /* tp_traverse */
(inquiry)buffered_clear, /* tp_clear */ (inquiry)buffered_clear, /* tp_clear */
@ -2597,7 +2596,7 @@ PyTypeObject PyBufferedRWPair_Type = {
0, /*tp_setattro*/ 0, /*tp_setattro*/
0, /*tp_as_buffer*/ 0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
| Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */ | Py_TPFLAGS_HAVE_GC, /* tp_flags */
_io_BufferedRWPair___init____doc__, /* tp_doc */ _io_BufferedRWPair___init____doc__, /* tp_doc */
(traverseproc)bufferedrwpair_traverse, /* tp_traverse */ (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
(inquiry)bufferedrwpair_clear, /* tp_clear */ (inquiry)bufferedrwpair_clear, /* tp_clear */
@ -2691,7 +2690,7 @@ PyTypeObject PyBufferedRandom_Type = {
0, /*tp_setattro*/ 0, /*tp_setattro*/
0, /*tp_as_buffer*/ 0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
| Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
_io_BufferedRandom___init____doc__, /* tp_doc */ _io_BufferedRandom___init____doc__, /* tp_doc */
(traverseproc)buffered_traverse, /* tp_traverse */ (traverseproc)buffered_traverse, /* tp_traverse */
(inquiry)buffered_clear, /* tp_clear */ (inquiry)buffered_clear, /* tp_clear */

View File

@ -1200,12 +1200,12 @@ PyTypeObject PyFileIO_Type = {
0, /* tp_setattro */ 0, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
| Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */ | Py_TPFLAGS_HAVE_GC, /* tp_flags */
_io_FileIO___init____doc__, /* tp_doc */ _io_FileIO___init____doc__, /* tp_doc */
(traverseproc)fileio_traverse, /* tp_traverse */ (traverseproc)fileio_traverse, /* tp_traverse */
(inquiry)fileio_clear, /* tp_clear */ (inquiry)fileio_clear, /* tp_clear */
0, /* tp_richcompare */ 0, /* tp_richcompare */
offsetof(fileio, weakreflist), /* tp_weaklistoffset */ offsetof(fileio, weakreflist), /* tp_weaklistoffset */
0, /* tp_iter */ 0, /* tp_iter */
0, /* tp_iternext */ 0, /* tp_iternext */
fileio_methods, /* tp_methods */ fileio_methods, /* tp_methods */
@ -1215,7 +1215,7 @@ PyTypeObject PyFileIO_Type = {
0, /* tp_dict */ 0, /* tp_dict */
0, /* tp_descr_get */ 0, /* tp_descr_get */
0, /* tp_descr_set */ 0, /* tp_descr_set */
offsetof(fileio, dict), /* tp_dictoffset */ offsetof(fileio, dict), /* tp_dictoffset */
_io_FileIO___init__, /* tp_init */ _io_FileIO___init__, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */ PyType_GenericAlloc, /* tp_alloc */
fileio_new, /* tp_new */ fileio_new, /* tp_new */

View File

@ -856,7 +856,7 @@ PyTypeObject PyIOBase_Type = {
0, /*tp_setattro*/ 0, /*tp_setattro*/
0, /*tp_as_buffer*/ 0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
| Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
iobase_doc, /* tp_doc */ iobase_doc, /* tp_doc */
(traverseproc)iobase_traverse, /* tp_traverse */ (traverseproc)iobase_traverse, /* tp_traverse */
(inquiry)iobase_clear, /* tp_clear */ (inquiry)iobase_clear, /* tp_clear */
@ -1051,7 +1051,7 @@ PyTypeObject PyRawIOBase_Type = {
0, /*tp_getattro*/ 0, /*tp_getattro*/
0, /*tp_setattro*/ 0, /*tp_setattro*/
0, /*tp_as_buffer*/ 0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
rawiobase_doc, /* tp_doc */ rawiobase_doc, /* tp_doc */
0, /* tp_traverse */ 0, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */

View File

@ -183,8 +183,7 @@ PyTypeObject PyTextIOBase_Type = {
0, /*tp_getattro*/ 0, /*tp_getattro*/
0, /*tp_setattro*/ 0, /*tp_setattro*/
0, /*tp_as_buffer*/ 0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
| Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
textiobase_doc, /* tp_doc */ textiobase_doc, /* tp_doc */
0, /* tp_traverse */ 0, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
@ -3258,7 +3257,7 @@ PyTypeObject PyTextIOWrapper_Type = {
0, /*tp_setattro*/ 0, /*tp_setattro*/
0, /*tp_as_buffer*/ 0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
| Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
_io_TextIOWrapper___init____doc__, /* tp_doc */ _io_TextIOWrapper___init____doc__, /* tp_doc */
(traverseproc)textiowrapper_traverse, /* tp_traverse */ (traverseproc)textiowrapper_traverse, /* tp_traverse */
(inquiry)textiowrapper_clear, /* tp_clear */ (inquiry)textiowrapper_clear, /* tp_clear */

View File

@ -1133,7 +1133,7 @@ PyTypeObject PyWindowsConsoleIO_Type = {
0, /* tp_setattro */ 0, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
| Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */ | Py_TPFLAGS_HAVE_GC, /* tp_flags */
_io__WindowsConsoleIO___init____doc__, /* tp_doc */ _io__WindowsConsoleIO___init____doc__, /* tp_doc */
(traverseproc)winconsoleio_traverse, /* tp_traverse */ (traverseproc)winconsoleio_traverse, /* tp_traverse */
(inquiry)winconsoleio_clear, /* tp_clear */ (inquiry)winconsoleio_clear, /* tp_clear */

View File

@ -98,7 +98,7 @@ static PyType_Spec Example_Type_spec = {
"_testimportexec.Example", "_testimportexec.Example",
sizeof(ExampleObject), sizeof(ExampleObject),
0, 0,
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Example_Type_slots Example_Type_slots
}; };

View File

@ -858,7 +858,6 @@ finalize_garbage(PyGC_Head *collectable)
PyObject *op = FROM_GC(gc); PyObject *op = FROM_GC(gc);
gc_list_move(gc, &seen); gc_list_move(gc, &seen);
if (!_PyGCHead_FINALIZED(gc) && if (!_PyGCHead_FINALIZED(gc) &&
PyType_HasFeature(Py_TYPE(op), Py_TPFLAGS_HAVE_FINALIZE) &&
(finalize = Py_TYPE(op)->tp_finalize) != NULL) { (finalize = Py_TYPE(op)->tp_finalize) != NULL) {
_PyGCHead_SET_FINALIZED(gc); _PyGCHead_SET_FINALIZED(gc);
Py_INCREF(op); Py_INCREF(op);

View File

@ -13032,8 +13032,7 @@ static PyTypeObject ScandirIteratorType = {
0, /* tp_getattro */ 0, /* tp_getattro */
0, /* tp_setattro */ 0, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT Py_TPFLAGS_DEFAULT, /* tp_flags */
| Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */
0, /* tp_doc */ 0, /* tp_doc */
0, /* tp_traverse */ 0, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */

View File

@ -5286,8 +5286,7 @@ static PyTypeObject sock_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_BASETYPE Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
| Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */
sock_doc, /* tp_doc */ sock_doc, /* tp_doc */
0, /* tp_traverse */ 0, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */

View File

@ -123,7 +123,7 @@ static PyType_Spec Xxo_Type_spec = {
"xxlimited.Xxo", "xxlimited.Xxo",
sizeof(XxoObject), sizeof(XxoObject),
0, 0,
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Xxo_Type_slots Xxo_Type_slots
}; };

View File

@ -742,8 +742,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_FINALIZE, /* tp_flags */
0, /* tp_doc */ 0, /* tp_doc */
(traverseproc)gen_traverse, /* tp_traverse */ (traverseproc)gen_traverse, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
@ -997,8 +996,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_FINALIZE, /* tp_flags */
0, /* tp_doc */ 0, /* tp_doc */
(traverseproc)gen_traverse, /* tp_traverse */ (traverseproc)gen_traverse, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
@ -1394,8 +1392,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_FINALIZE, /* 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

@ -298,10 +298,7 @@ PyObject_CallFinalizer(PyObject *self)
{ {
PyTypeObject *tp = Py_TYPE(self); PyTypeObject *tp = Py_TYPE(self);
/* The former could happen on heaptypes created from the C API, e.g. if (tp->tp_finalize == NULL)
PyType_FromSpec(). */
if (!PyType_HasFeature(tp, Py_TPFLAGS_HAVE_FINALIZE) ||
tp->tp_finalize == NULL)
return; return;
/* tp_finalize should only be called once. */ /* tp_finalize should only be called once. */
if (PyType_IS_GC(tp) && _PyGC_FINALIZED(self)) if (PyType_IS_GC(tp) && _PyGC_FINALIZED(self))

View File

@ -248,8 +248,8 @@ PyType_Modified(PyTypeObject *type)
Invariants: Invariants:
- Py_TPFLAGS_VALID_VERSION_TAG is never set if - Py_TPFLAGS_VALID_VERSION_TAG is never set if
Py_TPFLAGS_HAVE_VERSION_TAG is not set (e.g. on type Py_TPFLAGS_HAVE_VERSION_TAG is not set (in case of a
objects coming from non-recompiled extension modules) 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.
@ -2571,7 +2571,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
/* Initialize tp_flags */ /* Initialize tp_flags */
type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE | type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE |
Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_FINALIZE; Py_TPFLAGS_BASETYPE;
if (base->tp_flags & Py_TPFLAGS_HAVE_GC) if (base->tp_flags & Py_TPFLAGS_HAVE_GC)
type->tp_flags |= Py_TPFLAGS_HAVE_GC; type->tp_flags |= Py_TPFLAGS_HAVE_GC;
@ -5179,10 +5179,7 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
COPYSLOT(tp_init); COPYSLOT(tp_init);
COPYSLOT(tp_alloc); COPYSLOT(tp_alloc);
COPYSLOT(tp_is_gc); COPYSLOT(tp_is_gc);
if ((type->tp_flags & Py_TPFLAGS_HAVE_FINALIZE) && COPYSLOT(tp_finalize);
(base->tp_flags & Py_TPFLAGS_HAVE_FINALIZE)) {
COPYSLOT(tp_finalize);
}
if ((type->tp_flags & Py_TPFLAGS_HAVE_GC) == if ((type->tp_flags & Py_TPFLAGS_HAVE_GC) ==
(base->tp_flags & Py_TPFLAGS_HAVE_GC)) { (base->tp_flags & Py_TPFLAGS_HAVE_GC)) {
/* They agree about gc. */ /* They agree about gc. */