gh-41779: Allow defining any __slots__ for a class derived from tuple

This commit is contained in:
Serhiy Storchaka 2025-11-19 19:11:37 +02:00
parent 3149d64c93
commit a452fce1f5
8 changed files with 61 additions and 10 deletions

View file

@ -139,6 +139,7 @@ _PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters
#define SPEC_FAIL_ATTR_METACLASS_OVERRIDDEN 34
#define SPEC_FAIL_ATTR_SPLIT_DICT 35
#define SPEC_FAIL_ATTR_DESCR_NOT_DEFERRED 36
#define SPEC_FAIL_ATTR_SLOT_AFTER_ITEMS 37
/* Binary subscr and store subscr */
@ -810,6 +811,10 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject*
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);
return -1;
}
if (dmem->flags & _Py_AFTER_ITEMS) {
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_SLOT_AFTER_ITEMS);
return -1;
}
if (dmem->flags & Py_AUDIT_READ) {
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_AUDITED_SLOT);
return -1;
@ -1004,6 +1009,10 @@ _Py_Specialize_StoreAttr(_PyStackRef owner_st, _Py_CODEUNIT *instr, PyObject *na
SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_EXPECTED_ERROR);
goto fail;
}
if (dmem->flags & _Py_AFTER_ITEMS) {
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_SLOT_AFTER_ITEMS);
goto fail;
}
if (dmem->flags & Py_READONLY) {
SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_READ_ONLY);
goto fail;

View file

@ -20,6 +20,17 @@ member_get_object(const char *addr, const char *obj_addr, PyMemberDef *l)
return v;
}
void *
_PyMember_GetOffset(PyObject *obj, PyMemberDef *mp)
{
unsigned char *addr = (unsigned char *)obj + mp->offset;
if (mp->flags & _Py_AFTER_ITEMS) {
PyTypeObject *type = Py_TYPE(obj);
addr += _Py_SIZE_ROUND_UP(Py_SIZE(obj) * type->tp_itemsize, SIZEOF_VOID_P);
}
return addr;
}
PyObject *
PyMember_GetOne(const char *obj_addr, PyMemberDef *l)
{
@ -31,7 +42,7 @@ PyMember_GetOne(const char *obj_addr, PyMemberDef *l)
return NULL;
}
const char* addr = obj_addr + l->offset;
const void *addr = _PyMember_GetOffset((PyObject *)obj_addr, l);
switch (l->type) {
case Py_T_BOOL:
v = PyBool_FromLong(FT_ATOMIC_LOAD_CHAR_RELAXED(*(char*)addr));
@ -80,7 +91,7 @@ PyMember_GetOne(const char *obj_addr, PyMemberDef *l)
v = PyUnicode_FromString((char*)addr);
break;
case Py_T_CHAR: {
char char_val = FT_ATOMIC_LOAD_CHAR_RELAXED(*addr);
char char_val = FT_ATOMIC_LOAD_CHAR_RELAXED(*(char*)addr);
v = PyUnicode_FromStringAndSize(&char_val, 1);
break;
}
@ -151,10 +162,8 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
return -1;
}
#ifdef Py_GIL_DISABLED
PyObject *obj = (PyObject *) addr;
#endif
addr += l->offset;
PyObject *obj = (PyObject *)addr;
addr = _PyMember_GetOffset(obj, l);
if ((l->flags & Py_READONLY))
{