From 35a84944e2d85f684fd0faa9365e5c0db33b6013 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Fri, 15 Aug 2025 08:56:20 -0400 Subject: [PATCH 1/4] Improve the Py_REFCNT() documentation for 3.14. --- Doc/c-api/refcounting.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Doc/c-api/refcounting.rst b/Doc/c-api/refcounting.rst index 57a0728d4e9af4..9bcde3ed78048b 100644 --- a/Doc/c-api/refcounting.rst +++ b/Doc/c-api/refcounting.rst @@ -19,7 +19,7 @@ of Python objects. references to the object are actually held. For example, some objects are :term:`immortal` and have a very high refcount that does not reflect the actual number of references. Consequently, do not rely - on the returned value to be accurate, other than a value of 0 or 1. + on the returned value to be accurate. Use the :c:func:`Py_SET_REFCNT()` function to set an object reference count. @@ -38,6 +38,12 @@ of Python objects. .. versionchanged:: 3.11 The parameter type is no longer :c:expr:`const PyObject*`. + .. versionchanged:: 3.14 + The interpreter now uses :term:`borrowed references ` + where possible when calling C extensions. This means that an object's + reference count may appear as 1, even when it is not solely referenced by + the caller. + .. c:function:: void Py_SET_REFCNT(PyObject *o, Py_ssize_t refcnt) From ee1f95be93fbfbe6bf4b0745857f4bca99ab3a4c Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Fri, 15 Aug 2025 09:07:47 -0400 Subject: [PATCH 2/4] Improve 3.14 whatsnew about reference counting changes. --- Doc/whatsnew/3.14.rst | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index f33c20fbf31c0a..863f2fe7364329 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -3046,10 +3046,12 @@ Porting to Python 3.14 * The interpreter internally avoids some reference count modifications when loading objects onto the operands stack by :term:`borrowing ` references when possible. This can lead to smaller reference count values - compared to previous Python versions. C API extensions that checked - :c:func:`Py_REFCNT` of ``1`` to determine if an function argument is not - referenced by any other code should instead use - :c:func:`PyUnstable_Object_IsUniqueReferencedTemporary` as a safer replacement. + compared to previous Python versions, because the creation of :term:`strong + references ` is avoided in the Python interpreter. This + generally does not affect existing code, but C API extensions that checked + :c:func:`Py_REFCNT` of ``1`` to determine if an object is not referenced by + any other code should instead use :c:func:`PyUnstable_Object_IsUniqueReferencedTemporary` + as a safer replacement. * Private functions promoted to public C APIs: From b807f770d5440b4f8141cc8f16d334f1a196cae0 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Fri, 15 Aug 2025 09:38:30 -0400 Subject: [PATCH 3/4] Use a clearer note for Py_REFCNT(). --- Doc/c-api/refcounting.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Doc/c-api/refcounting.rst b/Doc/c-api/refcounting.rst index 9bcde3ed78048b..9d721997b7e885 100644 --- a/Doc/c-api/refcounting.rst +++ b/Doc/c-api/refcounting.rst @@ -39,10 +39,8 @@ of Python objects. The parameter type is no longer :c:expr:`const PyObject*`. .. versionchanged:: 3.14 - The interpreter now uses :term:`borrowed references ` - where possible when calling C extensions. This means that an object's - reference count may appear as 1, even when it is not solely referenced by - the caller. + A return value of 1 is no longer sufficient to determine that *o* is + solely referenced by the caller. .. c:function:: void Py_SET_REFCNT(PyObject *o, Py_ssize_t refcnt) From ad6c98cad25d6d9e2afd11eaa77b3bb637ef5aa2 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Fri, 15 Aug 2025 09:44:57 -0400 Subject: [PATCH 4/4] Try to clarify that this is a breaking change in Python 3.14. --- Doc/whatsnew/3.14.rst | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 863f2fe7364329..e1c807a4cf4e40 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -3047,11 +3047,15 @@ Porting to Python 3.14 loading objects onto the operands stack by :term:`borrowing ` references when possible. This can lead to smaller reference count values compared to previous Python versions, because the creation of :term:`strong - references ` is avoided in the Python interpreter. This - generally does not affect existing code, but C API extensions that checked - :c:func:`Py_REFCNT` of ``1`` to determine if an object is not referenced by - any other code should instead use :c:func:`PyUnstable_Object_IsUniqueReferencedTemporary` - as a safer replacement. + references ` is avoided in the Python interpreter. + + This means that in Python 3.14, the :term:`reference count` of an object can + be ``1`` even when an object has more than one reference in the interpreter + stack. This generally does not affect existing code, but C API extensions + that checked :c:func:`Py_REFCNT` of ``1`` to determine if an object is not + referenced by any other code should instead use + :c:func:`PyUnstable_Object_IsUniqueReferencedTemporary` as a safer + replacement. * Private functions promoted to public C APIs: