diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-06-11-21-40-21.gh-issue-135385.e2TFON.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-06-11-21-40-21.gh-issue-135385.e2TFON.rst new file mode 100644 index 00000000000000..99824404dfd7f4 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-06-11-21-40-21.gh-issue-135385.e2TFON.rst @@ -0,0 +1,2 @@ +Fix a memory regression for classes that have both :attr:`~object.__slots__` and +:attr:`~object.__dict__`. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index db923c164774b7..1e974669ba20a7 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4621,7 +4621,19 @@ type_new_descriptors(const type_new_ctx *ctx, PyTypeObject *type) } type->tp_basicsize = slotoffset; - type->tp_itemsize = ctx->base->tp_itemsize; + + // Only inherit tp_itemsize if this type defines its own __slots__ + // Classes that don't define __slots__ but inherit from __slots__ classes + // should not inherit tp_itemsize as they don't use variable-size items + if (et->ht_slots != NULL && PyTuple_GET_SIZE(et->ht_slots) > 0) { + // This type defines its own __slots__, inherit tp_itemsize + type->tp_itemsize = ctx->base->tp_itemsize; + } + else { + // This type doesn't define __slots__, don't inherit tp_itemsize + type->tp_itemsize = 0; + } + type->tp_members = _PyHeapType_GET_MEMBERS(et); return 0; }