bpo-36974: inherit tp_vectorcall_offset unconditionally (GH-13858) (GH-14342)

(cherry picked from commit a8b27e623d)

Co-authored-by: Jeroen Demeyer <J.Demeyer@UGent.be>
This commit is contained in:
Miss Islington (bot) 2019-06-25 01:19:16 -07:00 committed by Petr Viktorin
parent 20372d6524
commit 26fe6c3537
4 changed files with 18 additions and 7 deletions

View file

@ -577,9 +577,18 @@ class TestPEP590(unittest.TestCase):
def __call__(self, n): def __call__(self, n):
return 'new' return 'new'
class SuperBase:
def __call__(self, *args):
return super().__call__(*args)
class MethodDescriptorSuper(SuperBase, _testcapi.MethodDescriptorBase):
def __call__(self, *args):
return super().__call__(*args)
calls += [ calls += [
(MethodDescriptorHeap(), (0,), {}, True), (MethodDescriptorHeap(), (0,), {}, True),
(MethodDescriptorOverridden(), (0,), {}, 'new'), (MethodDescriptorOverridden(), (0,), {}, 'new'),
(MethodDescriptorSuper(), (0,), {}, True),
] ]
for (func, args, kwargs, expected) in calls: for (func, args, kwargs, expected) in calls:

View file

@ -0,0 +1,2 @@
The slot ``tp_vectorcall_offset`` is inherited unconditionally to support
``super().__call__()`` when the base class uses vectorcall.

View file

@ -176,7 +176,7 @@ PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwargs)
/* get vectorcallfunc as in _PyVectorcall_Function, but without /* get vectorcallfunc as in _PyVectorcall_Function, but without
* the _Py_TPFLAGS_HAVE_VECTORCALL check */ * the _Py_TPFLAGS_HAVE_VECTORCALL check */
Py_ssize_t offset = Py_TYPE(callable)->tp_vectorcall_offset; Py_ssize_t offset = Py_TYPE(callable)->tp_vectorcall_offset;
if ((offset <= 0) || (!Py_TYPE(callable)->tp_call)) { if (offset <= 0) {
PyErr_Format(PyExc_TypeError, "'%.200s' object does not support vectorcall", PyErr_Format(PyExc_TypeError, "'%.200s' object does not support vectorcall",
Py_TYPE(callable)->tp_name); Py_TYPE(callable)->tp_name);
return NULL; return NULL;

View file

@ -5148,15 +5148,15 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
COPYSLOT(tp_repr); COPYSLOT(tp_repr);
/* tp_hash see tp_richcompare */ /* tp_hash see tp_richcompare */
{ {
/* Inherit tp_vectorcall_offset only if tp_call is not overridden */ /* Always inherit tp_vectorcall_offset to support PyVectorcall_Call().
if (!type->tp_call) { * If _Py_TPFLAGS_HAVE_VECTORCALL is not inherited, then vectorcall
COPYSLOT(tp_vectorcall_offset); * won't be used automatically. */
} COPYSLOT(tp_vectorcall_offset);
/* Inherit_Py_TPFLAGS_HAVE_VECTORCALL for non-heap types
/* Inherit _Py_TPFLAGS_HAVE_VECTORCALL for non-heap types
* if tp_call is not overridden */ * if tp_call is not overridden */
if (!type->tp_call && if (!type->tp_call &&
(base->tp_flags & _Py_TPFLAGS_HAVE_VECTORCALL) && (base->tp_flags & _Py_TPFLAGS_HAVE_VECTORCALL) &&
!(type->tp_flags & _Py_TPFLAGS_HAVE_VECTORCALL) &&
!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) !(type->tp_flags & Py_TPFLAGS_HEAPTYPE))
{ {
type->tp_flags |= _Py_TPFLAGS_HAVE_VECTORCALL; type->tp_flags |= _Py_TPFLAGS_HAVE_VECTORCALL;