Description
The mutability of PyTypeObject
(builtin classes) and the shareability of statically allocated (C) objects makes safe handling of builtin types fragile, difficult, and ultimately unsafe.
Whereas, immutable objects are great for free-threading and multiple interpreters. They can be freely shared and there are no race conditions, and for immortal objects no contention when using them.
Immortal, immutable objects are also much easier to use from C code. Accessing int
class is easy: &PyLong_Type
. But accessing array.array
is a real pain, requiring API calls.
We are making unreasonable demands of third-party code to support multiple interpreters, for code that used to be simple.
We can provide immutable, sharable PyTypeObject
s with a simple, easy to use API that makes it easy to port old code with the following few API changes:
-
Strip the
PyObject_VAR_HEAD
from the start ofstruct _typeobject
making it a plain C struct,struct _classdef
not a Python object. -
Make
PyTypeObject
an opaque struct -
Provide an API to create a
PyTypeObject
from astruct _classdef
:int Py_MakeClass(struct _classdef def, PyInterpreterState *interp, PyTypeObject **result)
-
interp == NULL
. The result would be a pointer to an immortal and immortal class. -
interp != NULL
. The result would be a new reference to a mortal, mutable class belonging to the given interpreter.
The sooner we can make PyTypeObject
opaque, the better, but we might need to keep it open for a release or two for backwards compatibility reasons.