diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst index 05c54ccc8da..49f2a614e35 100644 --- a/Doc/c-api/structures.rst +++ b/Doc/c-api/structures.rst @@ -99,7 +99,10 @@ the definition of all other Python objects. Return a :term:`borrowed reference`. - The :c:func:`Py_SET_TYPE` function must be used to set an object type. + Use the :c:func:`Py_SET_TYPE` function to set an object type. + + .. versionchanged:: 3.11 + :c:func:`Py_TYPE()` is changed to an inline static function. .. c:function:: int Py_IS_TYPE(PyObject *o, PyTypeObject *type) @@ -121,9 +124,10 @@ the definition of all other Python objects. Get the reference count of the Python object *o*. + Use the :c:func:`Py_SET_REFCNT()` function to set an object reference count. + .. versionchanged:: 3.10 :c:func:`Py_REFCNT()` is changed to the inline static function. - Use :c:func:`Py_SET_REFCNT()` to set an object reference count. .. c:function:: void Py_SET_REFCNT(PyObject *o, Py_ssize_t refcnt) @@ -137,7 +141,10 @@ the definition of all other Python objects. Get the size of the Python object *o*. - The :c:func:`Py_SET_SIZE` function must be used to set an object size. + Use the :c:func:`Py_SET_SIZE` function to set an object size. + + .. versionchanged:: 3.11 + :c:func:`Py_SIZE()` is changed to an inline static function. .. c:function:: void Py_SET_SIZE(PyVarObject *o, Py_ssize_t size) diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 60ef953d2ec..30ee182718d 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -402,6 +402,34 @@ Porting to Python 3.11 :ref:`static types `. (Contributed by Erlend E. Aasland in :issue:`43908`) +* Since :c:func:`Py_TYPE()` is changed to a inline static function, + ``Py_TYPE(obj) = new_type`` must be replaced with + ``Py_SET_TYPE(obj, new_type)``: see the :c:func:`Py_SET_TYPE()` function + (available since Python 3.9). For backward compatibility, this macro can be + used:: + + #if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE) + static inline void _Py_SET_TYPE(PyObject *ob, PyTypeObject *type) + { ob->ob_type = type; } + #define Py_SET_TYPE(ob, type) _Py_SET_TYPE((PyObject*)(ob), type) + #endif + + (Contributed by Victor Stinner in :issue:`39573`.) + +* Since :c:func:`Py_SIZE()` is changed to a inline static function, + ``Py_SIZE(obj) = new_size`` must be replaced with + ``Py_SET_SIZE(obj, new_size)``: see the :c:func:`Py_SET_SIZE()` function + (available since Python 3.9). For backward compatibility, this macro can be + used:: + + #if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_SIZE) + static inline void _Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) + { ob->ob_size = size; } + #define Py_SET_SIZE(ob, size) _Py_SET_SIZE((PyVarObject*)(ob), size) + #endif + + (Contributed by Victor Stinner in :issue:`39573`.) + Deprecated ---------- diff --git a/Include/object.h b/Include/object.h index fb8a63fc7db..490cbffd5f1 100644 --- a/Include/object.h +++ b/Include/object.h @@ -134,10 +134,16 @@ static inline Py_ssize_t _Py_REFCNT(const PyObject *ob) { // bpo-39573: The Py_SET_TYPE() function must be used to set an object type. -#define Py_TYPE(ob) (_PyObject_CAST(ob)->ob_type) +static inline PyTypeObject* _Py_TYPE(const PyObject *ob) { + return ob->ob_type; +} +#define Py_TYPE(ob) _Py_TYPE(_PyObject_CAST_CONST(ob)) // bpo-39573: The Py_SET_SIZE() function must be used to set an object size. -#define Py_SIZE(ob) (_PyVarObject_CAST(ob)->ob_size) +static inline Py_ssize_t _Py_SIZE(const PyVarObject *ob) { + return ob->ob_size; +} +#define Py_SIZE(ob) _Py_SIZE(_PyVarObject_CAST_CONST(ob)) static inline int _Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) { diff --git a/Misc/NEWS.d/next/C API/2021-06-03-00-59-48.bpo-39573.-elHTJ.rst b/Misc/NEWS.d/next/C API/2021-06-03-00-59-48.bpo-39573.-elHTJ.rst new file mode 100644 index 00000000000..d9641ed97e1 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2021-06-03-00-59-48.bpo-39573.-elHTJ.rst @@ -0,0 +1,3 @@ +Convert the :c:func:`Py_TYPE` and :c:func:`Py_SIZE` macros to static inline +functions. The :c:func:`Py_SET_TYPE` and :c:func:`Py_SET_SIZE` functions +must now be used to set an object type and size. Patch by Victor Stinner. diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 68dd285c380..b1e64f19f2d 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -5511,10 +5511,9 @@ test_set_type_size(PyObject *self, PyObject *Py_UNUSED(ignored)) assert(Py_TYPE(obj) == &PyList_Type); assert(Py_SIZE(obj) == 0); - // bpo-39573: Check that Py_TYPE() and Py_SIZE() can be used - // as l-values to set an object type and size. - Py_TYPE(obj) = &PyList_Type; - Py_SIZE(obj) = 0; + // bpo-39573: Test Py_SET_TYPE() and Py_SET_SIZE() functions. + Py_SET_TYPE(obj, &PyList_Type); + Py_SET_SIZE(obj, 0); Py_DECREF(obj); Py_RETURN_NONE;