gh-100554: Add `Py_tp_vectorcall slot to set PyTypeObject.tp_vectorcall using the PyType_FromSpec` function family. (#123332)

This commit is contained in:
Wenzel Jakob 2024-09-14 00:40:25 +09:00 committed by GitHub
parent bbb36c0934
commit 74330d992b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 147 additions and 10 deletions

View file

@ -504,11 +504,8 @@ The following functions and structs are used to create
See :ref:`PyMemberDef documentation <pymemberdef-offsets>`
for details.
The following fields cannot be set at all when creating a heap type:
* :c:member:`~PyTypeObject.tp_vectorcall`
(use :c:member:`~PyTypeObject.tp_new` and/or
:c:member:`~PyTypeObject.tp_init`)
The following internal fields cannot be set at all when creating a heap
type:
* Internal fields:
:c:member:`~PyTypeObject.tp_dict`,
@ -531,6 +528,12 @@ The following functions and structs are used to create
:c:member:`~PyBufferProcs.bf_releasebuffer` are now available
under the :ref:`limited API <limited-c-api>`.
.. versionchanged:: 3.14
The field :c:member:`~PyTypeObject.tp_vectorcall` can now set
using ``Py_tp_vectorcall``. See the field's documentation
for details.
.. c:member:: void *pfunc
The desired value of the slot. In most cases, this is a pointer

View file

@ -2137,11 +2137,40 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: vectorcallfunc PyTypeObject.tp_vectorcall
Vectorcall function to use for calls of this type object.
In other words, it is used to implement
:ref:`vectorcall <vectorcall>` for ``type.__call__``.
If ``tp_vectorcall`` is ``NULL``, the default call implementation
using :meth:`~object.__new__` and :meth:`~object.__init__` is used.
A :ref:`vectorcall function <vectorcall>` to use for calls of this type
object (rather than instances).
In other words, ``tp_vectorcall`` can be used to optimize ``type.__call__``,
which typically returns a new instance of *type*.
As with any vectorcall function, if ``tp_vectorcall`` is ``NULL``,
the *tp_call* protocol (``Py_TYPE(type)->tp_call``) is used instead.
.. note::
The :ref:`vectorcall protocol <vectorcall>` requires that the vectorcall
function has the same behavior as the corresponding ``tp_call``.
This means that ``type->tp_vectorcall`` must match the behavior of
``Py_TYPE(type)->tp_call``.
Specifically, if *type* uses the default metaclass,
``type->tp_vectorcall`` must behave the same as
:c:expr:`PyType_Type->tp_call`, which:
- calls ``type->tp_new``,
- if the result is a subclass of *type*, calls ``type->tp_init``
on the result of ``tp_new``, and
- returns the result of ``tp_new``.
Typically, ``tp_vectorcall`` is overridden to optimize this process
for specific :c:member:`~PyTypeObject.tp_new` and
:c:member:`~PyTypeObject.tp_init`.
When doing this for user-subclassable types, note that both can be
overridden (using :py:func:`~object.__new__` and
:py:func:`~object.__init__`, respectively).
**Inheritance:**