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

File tree

4 files changed

lines changed

4 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -577,9 +577,18 @@ class MethodDescriptorOverridden(_testcapi.MethodDescriptorBase):
577 577 def __call__(self, n):
578 578 return 'new'
579 579
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 +
580 588 calls += [
581 589 (MethodDescriptorHeap(), (0,), {}, True),
582 590 (MethodDescriptorOverridden(), (0,), {}, 'new'),
591 + (MethodDescriptorSuper(), (0,), {}, True),
583 592 ]
584 593
585 594 for (func, args, kwargs, expected) in calls:
Original file line number Diff line number Diff 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 number Diff line number Diff line change
@@ -184,7 +184,7 @@ PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwargs)
184 184 /* get vectorcallfunc as in _PyVectorcall_Function, but without
185 185 * the _Py_TPFLAGS_HAVE_VECTORCALL check */
186 186 Py_ssize_t offset = Py_TYPE(callable)->tp_vectorcall_offset;
187 -if ((offset <= 0) |
187 +if (offset <= 0) {
188 188 PyErr_Format(PyExc_TypeError, "'%.200s' object does not support vectorcall",
189 189 Py_TYPE(callable)->tp_name);
190 190 return NULL;
Original file line number Diff line number Diff line change
@@ -5153,15 +5153,15 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
5153 5153 COPYSLOT(tp_repr);
5154 5154 /* tp_hash see tp_richcompare */
5155 5155 {
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
5161 5162 * if tp_call is not overridden */
5162 5163 if (!type->tp_call &&
5163 5164 (base->tp_flags & _Py_TPFLAGS_HAVE_VECTORCALL) &&
5164 - !(type->tp_flags & _Py_TPFLAGS_HAVE_VECTORCALL) &&
5165 5165 !(type->tp_flags & Py_TPFLAGS_HEAPTYPE))
5166 5166 {
5167 5167 type->tp_flags |= _Py_TPFLAGS_HAVE_VECTORCALL;