@@ -158,6 +158,12 @@ _PyType_CheckConsistency(PyTypeObject *type)
158
158
CHECK (!(type -> tp_flags & Py_TPFLAGS_READYING ));
159
159
CHECK (type -> tp_dict != NULL );
160
160
161
+ if (type -> tp_flags & Py_TPFLAGS_HAVE_GC ) {
162
+ // bpo-44263: tp_traverse is required if Py_TPFLAGS_HAVE_GC is set.
163
+ // Note: tp_clear is optional.
164
+ CHECK (type -> tp_traverse != NULL );
165
+ }
166
+
161
167
if (type -> tp_flags & Py_TPFLAGS_DISALLOW_INSTANTIATION ) {
162
168
CHECK (type -> tp_new == NULL );
163
169
CHECK (_PyDict_ContainsId (type -> tp_dict , & PyId___new__ ) == 0 );
@@ -3607,6 +3613,7 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases)
3607
3613
}
3608
3614
}
3609
3615
3616
+ assert (_PyType_CheckConsistency (type ));
3610
3617
return (PyObject * )res ;
3611
3618
3612
3619
fail :
@@ -5944,7 +5951,7 @@ static int add_tp_new_wrapper(PyTypeObject *type);
5944
5951
#define COLLECTION_FLAGS (Py_TPFLAGS_SEQUENCE | Py_TPFLAGS_MAPPING)
5945
5952
5946
5953
static int
5947
- type_ready_checks (PyTypeObject * type )
5954
+ type_ready_pre_checks (PyTypeObject * type )
5948
5955
{
5949
5956
/* Consistency checks for PEP 590:
5950
5957
* - Py_TPFLAGS_METHOD_DESCRIPTOR requires tp_descr_get
@@ -6305,10 +6312,28 @@ type_ready_set_new(PyTypeObject *type)
6305
6312
}
6306
6313
6307
6314
6315
+ static int
6316
+ type_ready_post_checks (PyTypeObject * type )
6317
+ {
6318
+ // bpo-44263: tp_traverse is required if Py_TPFLAGS_HAVE_GC is set.
6319
+ // Note: tp_clear is optional.
6320
+ if (type -> tp_flags & Py_TPFLAGS_HAVE_GC
6321
+ && type -> tp_traverse == NULL )
6322
+ {
6323
+ PyErr_Format (PyExc_SystemError ,
6324
+ "type %s has the Py_TPFLAGS_HAVE_GC flag "
6325
+ "but has no traverse function" ,
6326
+ type -> tp_name );
6327
+ return -1 ;
6328
+ }
6329
+ return 0 ;
6330
+ }
6331
+
6332
+
6308
6333
static int
6309
6334
type_ready (PyTypeObject * type )
6310
6335
{
6311
- if (type_ready_checks (type ) < 0 ) {
6336
+ if (type_ready_pre_checks (type ) < 0 ) {
6312
6337
return -1 ;
6313
6338
}
6314
6339
@@ -6346,6 +6371,9 @@ type_ready(PyTypeObject *type)
6346
6371
if (type_ready_add_subclasses (type ) < 0 ) {
6347
6372
return -1 ;
6348
6373
}
6374
+ if (type_ready_post_checks (type ) < 0 ) {
6375
+ return -1 ;
6376
+ }
6349
6377
return 0 ;
6350
6378
}
6351
6379
0 commit comments