bpo-36974: inherit tp_vectorcall_offset unconditionally (GH-13858) · python/cpython@a8b27e6

File tree

4 files changed

lines changed

  • Misc/NEWS.d/next/Core and Builtins

4 files changed

lines changed

Original file line numberDiff line numberDiff line change

@@ -577,9 +577,18 @@ class MethodDescriptorOverridden(_testcapi.MethodDescriptorBase):

577577

def __call__(self, n):

578578

return 'new'

579579
580+

class SuperBase:

581+

def __call__(self, *args):

582+

return super().__call__(*args)

583+
584+

class MethodDescriptorSuper(SuperBase, _testcapi.MethodDescriptorBase):

585+

def __call__(self, *args):

586+

return super().__call__(*args)

587+
580588

calls += [

581589

(MethodDescriptorHeap(), (0,), {}, True),

582590

(MethodDescriptorOverridden(), (0,), {}, 'new'),

591+

(MethodDescriptorSuper(), (0,), {}, True),

583592

]

584593
585594

for (func, args, kwargs, expected) in calls:

Original file line numberDiff line numberDiff line change

@@ -0,0 +1,2 @@

1+

The slot ``tp_vectorcall_offset`` is inherited unconditionally to support

2+

``super().__call__()`` when the base class uses vectorcall.

Original file line numberDiff line numberDiff line change

@@ -184,7 +184,7 @@ PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwargs)

184184

/* get vectorcallfunc as in _PyVectorcall_Function, but without

185185

* the _Py_TPFLAGS_HAVE_VECTORCALL check */

186186

Py_ssize_t offset = Py_TYPE(callable)->tp_vectorcall_offset;

187-

if ((offset <= 0) || (!Py_TYPE(callable)->tp_call)) {

187+

if (offset <= 0) {

188188

PyErr_Format(PyExc_TypeError, "'%.200s' object does not support vectorcall",

189189

Py_TYPE(callable)->tp_name);

190190

return NULL;

Original file line numberDiff line numberDiff line change

@@ -5153,15 +5153,15 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)

51535153

COPYSLOT(tp_repr);

51545154

/* tp_hash see tp_richcompare */

51555155

{

5156-

/* Inherit tp_vectorcall_offset only if tp_call is not overridden */

5157-

if (!type->tp_call) {

5158-

COPYSLOT(tp_vectorcall_offset);

5159-

}

5160-

/* Inherit_Py_TPFLAGS_HAVE_VECTORCALL for non-heap types

5156+

/* Always inherit tp_vectorcall_offset to support PyVectorcall_Call().

5157+

* If _Py_TPFLAGS_HAVE_VECTORCALL is not inherited, then vectorcall

5158+

* won't be used automatically. */

5159+

COPYSLOT(tp_vectorcall_offset);

5160+
5161+

/* Inherit _Py_TPFLAGS_HAVE_VECTORCALL for non-heap types

51615162

* if tp_call is not overridden */

51625163

if (!type->tp_call &&

51635164

(base->tp_flags & _Py_TPFLAGS_HAVE_VECTORCALL) &&

5164-

!(type->tp_flags & _Py_TPFLAGS_HAVE_VECTORCALL) &&

51655165

!(type->tp_flags & Py_TPFLAGS_HEAPTYPE))

51665166

{

51675167

type->tp_flags |= _Py_TPFLAGS_HAVE_VECTORCALL;