GH-132042: Fix calculation of slotdef index in update_one_slot#145880
GH-132042: Fix calculation of slotdef index in update_one_slot#145880vstinner merged 1 commit intopython:mainfrom
Conversation
|
On the first sight we should not face this error. I added extra checks and, it seems that the existing code is handling the situation well. Extra checks: I didn't see this message in the logs while Python was compiling and freezing. @vstinner Could you please take a look? |
|
Tests passed, no message in the logs. |
|
PR merged, thanks for the fix. Thanks @eendebakpt for the bug report! I tried different ways to check if the previous code had a bug, but I failed to find a case where the change makes any difference. We were just very lucky, the bug had no effects! |
|
I wrote a test on slots. I leave it here, I don't know if it's useful, so I don't propose a PR. diff --git a/Lib/test/test_capi/test_type.py b/Lib/test/test_capi/test_type.py
index e6a8ef9eed6..3b6fcb5e12a 100644
--- a/Lib/test/test_capi/test_type.py
+++ b/Lib/test/test_capi/test_type.py
@@ -299,3 +299,20 @@ def test_extension_managed_weakref_nogc_type(self):
"flag but not Py_TPFLAGS_HAVE_GC flag")
with self.assertRaisesRegex(SystemError, msg):
_testcapi.create_managed_weakref_nogc_type()
+
+ def test_type_slots_optim(self):
+ check_type_slots_optim = _testcapi.check_type_slots_optim
+
+ class UserType:
+ __hash__ = None
+ def __eq__(self, other):
+ return True
+ def __ne__(self, other):
+ return False
+ def __or__(self, other):
+ return 123
+
+ class SubClass(UserType):
+ pass
+
+ check_type_slots_optim(UserType, SubClass)
diff --git a/Modules/_testcapi/type.c b/Modules/_testcapi/type.c
index 9bef58d1f83..cbb7d45a35c 100644
--- a/Modules/_testcapi/type.c
+++ b/Modules/_testcapi/type.c
@@ -227,6 +227,43 @@ type_freeze(PyObject *module, PyObject *arg)
}
+static PyObject *
+check_type_slots_optim(PyObject *module, PyObject *args)
+{
+ PyTypeObject *user_type, *subclass;
+ if (!PyArg_ParseTuple(args, "O!O!",
+ &PyType_Type, &user_type,
+ &PyType_Type, &subclass)) {
+ return NULL;
+ }
+
+ // Methods inherited from object
+ PyTypeObject *object_type = &PyBaseObject_Type;
+ assert(user_type->tp_new == object_type->tp_new);
+ assert(user_type->tp_init == object_type->tp_init);
+ assert(user_type->tp_repr == object_type->tp_repr);
+ assert(user_type->tp_str == object_type->tp_str);
+
+ // Methods not defined
+ assert(user_type->tp_call == NULL);
+ assert(user_type->tp_as_number->nb_and == NULL);
+
+ // Methods implemented in Python
+ assert(user_type->tp_richcompare != NULL);
+ assert(user_type->tp_as_number->nb_or != NULL);
+
+ // __hash__ = None
+ assert(user_type->tp_hash == PyObject_HashNotImplemented);
+
+ // Test subclass
+ assert(subclass->tp_richcompare == user_type->tp_richcompare);
+ assert(subclass->tp_as_number->nb_or == user_type->tp_as_number->nb_or);
+ assert(subclass->tp_hash == user_type->tp_hash);
+
+ Py_RETURN_NONE;
+}
+
+
static PyMethodDef test_methods[] = {
{"get_heaptype_for_name", get_heaptype_for_name, METH_NOARGS},
{"get_type_name", get_type_name, METH_O},
@@ -241,6 +278,7 @@ static PyMethodDef test_methods[] = {
{"type_get_tp_bases", type_get_tp_bases, METH_O},
{"type_get_tp_mro", type_get_tp_mro, METH_O},
{"type_freeze", type_freeze, METH_O},
+ {"check_type_slots_optim", check_type_slots_optim, METH_VARARGS},
{NULL},
};
|
|
Thanks @sergey-miryanov for the PR, and @vstinner for merging it 🌮🎉.. I'm working now to backport this PR to: 3.14. |
|
Sorry, @sergey-miryanov and @vstinner, I could not cleanly backport this to |
|
I was sure it was implemented in 3.14. Sorry. |
There is a fix for calculation of the slotdef index.
Thanks @eendebakpt