bpo-36974: inherit tp_vectorcall_offset unconditionally (GH-13858) (G… · python/cpython@26fe6c3

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

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

176176

/* get vectorcallfunc as in _PyVectorcall_Function, but without

177177

* the _Py_TPFLAGS_HAVE_VECTORCALL check */

178178

Py_ssize_t offset = Py_TYPE(callable)->tp_vectorcall_offset;

179-

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

179+

if (offset <= 0) {

180180

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

181181

Py_TYPE(callable)->tp_name);

182182

return NULL;

Original file line numberDiff line numberDiff line change

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

51485148

COPYSLOT(tp_repr);

51495149

/* tp_hash see tp_richcompare */

51505150

{

5151-

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

5152-

if (!type->tp_call) {

5153-

COPYSLOT(tp_vectorcall_offset);

5154-

}

5155-

/* Inherit_Py_TPFLAGS_HAVE_VECTORCALL for non-heap types

5151+

/* Always inherit tp_vectorcall_offset to support PyVectorcall_Call().

5152+

* If _Py_TPFLAGS_HAVE_VECTORCALL is not inherited, then vectorcall

5153+

* won't be used automatically. */

5154+

COPYSLOT(tp_vectorcall_offset);

5155+
5156+

/* Inherit _Py_TPFLAGS_HAVE_VECTORCALL for non-heap types

51565157

* if tp_call is not overridden */

51575158

if (!type->tp_call &&

51585159

(base->tp_flags & _Py_TPFLAGS_HAVE_VECTORCALL) &&

5159-

!(type->tp_flags & _Py_TPFLAGS_HAVE_VECTORCALL) &&

51605160

!(type->tp_flags & Py_TPFLAGS_HEAPTYPE))

51615161

{

51625162

type->tp_flags |= _Py_TPFLAGS_HAVE_VECTORCALL;