Skip to content

PEP 590: update #1028

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions pep-0590.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Calls are made through a function pointer taking the following parameters:
* ``PyObject *callable``: The called object
* ``PyObject *const *args``: A vector of arguments
* ``Py_ssize_t nargs``: The number of arguments plus the optional flag ``PY_VECTORCALL_ARGUMENTS_OFFSET`` (see below)
* ``PyObject *kwnames``: Either ``NULL`` or a tuple with the names of the keyword arguments
* ``PyObject *kwnames``: Either ``NULL`` or a non-empty tuple with the names of the keyword arguments

This is implemented by the function pointer type:
``typedef PyObject *(*vectorcallfunc)(PyObject *callable, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames);``
Expand Down Expand Up @@ -99,6 +99,8 @@ The call
The call takes the form ``((vectorcallfunc)(((char *)o)+offset))(o, args, n, kwnames)`` where
``offset`` is ``Py_TYPE(o)->tp_vectorcall_offset``.
The caller is responsible for creating the ``kwnames`` tuple and ensuring that there are no duplicates in it.
For efficiently dealing with the common case of no keywords,
``kwnames`` must be ``NULL`` if there are no keyword arguments.

``n`` is the number of postional arguments plus possibly the ``PY_VECTORCALL_ARGUMENTS_OFFSET`` flag.

Expand Down Expand Up @@ -131,8 +133,8 @@ The following functions or macros are added to the C API:
Calls ``obj`` with the given arguments.
Note that ``nargs`` may include the flag ``PY_VECTORCALL_ARGUMENTS_OFFSET``.
The actual number of positional arguments is given by ``PyVectorcall_NARGS(nargs)``.
The argument ``keywords`` is a tuple of keyword names or ``NULL``.
An empty tuple has the same effect as passing ``NULL``.
The argument ``keywords`` is either a dict, a tuple of keyword names or ``NULL``.
An empty dict or empty tuple has the same effect as passing ``NULL``.
This uses either the vectorcall protocol or ``tp_call`` internally;
if neither is supported, an exception is raised.

Expand All @@ -149,7 +151,7 @@ New ``METH_VECTORCALL`` flag
----------------------------

A new constant ``METH_VECTORCALL`` is added for specifying ``PyMethodDef`` structs.
It means that the C function has the type ``PyObject *(*call) (PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwname)``.
It means that the C function has the signature ``vectorcallfunc``.
This should be the preferred flag for new functions, as this avoids a wrapper function.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a major change and prevents the interpreter from sanity checking the return value of PyMethodDef defined functions. The signature of METH_VECTORCALL should remain as
PyObject *(*call) (PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwname)

Copy link
Contributor Author

@jdemeyer jdemeyer May 7, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a major change and prevents the interpreter from sanity checking the return value of PyMethodDef defined functions.

Please explain. I don't think it's the job of the vectorcall callee to do that check, it should be done by the vectorcall caller.

For example, in your reference implementation, that check could be done by _Py_VectorCall.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it is the job of the callee to do this check. _PyCFunction_FastCallKeywords does this, as the PymethodDef defined code is not entirely trusted. However, calls to the interpreter or builtin classes are trusted and don't need to be double checked.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as the PymethodDef defined code is not entirely trusted.

Why should the PyMethodDef-defined code be less trusted than other code called by the vectorcall protocol? I don't see the difference.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because PyMethodDef remains the preferred way for builtin functions to be implemented if they are implemented in C. For tools like Cython that can ensure that the returned value is consistent, the additional check is not required.


**NOTE**: the numerical value of ``METH_VECTORCALL`` is unspecified
Expand Down