[Python-checkins] bpo-36974: inherit tp_vectorcall_offset unconditionally (GH-13858) (GH-14342)

Petr Viktorin webhook-mailer at python.org
Tue Jun 25 04:19:41 EDT 2019


https://github.com/python/cpython/commit/26fe6c35374fa32577b230b856a92a3b094e08ed
commit: 26fe6c35374fa32577b230b856a92a3b094e08ed
branch: 3.8
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: Petr Viktorin <encukou at gmail.com>
date: 2019-06-25T10:19:16+02:00
summary:

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

(cherry picked from commit a8b27e623d75377aabe50df27e97cab4e81a174a)

Co-authored-by: Jeroen Demeyer <J.Demeyer at UGent.be>

files:
A Misc/NEWS.d/next/Core and Builtins/2019-06-06-11-00-55.bpo-36974.wdzzym.rst
M Lib/test/test_call.py
M Objects/call.c
M Objects/typeobject.c

diff --git a/Lib/test/test_call.py b/Lib/test/test_call.py
index b4ab74903edb..b252ca1076ad 100644
--- a/Lib/test/test_call.py
+++ b/Lib/test/test_call.py
@@ -577,9 +577,18 @@ class MethodDescriptorOverridden(_testcapi.MethodDescriptorBase):
             def __call__(self, n):
                 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 += [
             (MethodDescriptorHeap(), (0,), {}, True),
             (MethodDescriptorOverridden(), (0,), {}, 'new'),
+            (MethodDescriptorSuper(), (0,), {}, True),
         ]
 
         for (func, args, kwargs, expected) in calls:
diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-06-06-11-00-55.bpo-36974.wdzzym.rst b/Misc/NEWS.d/next/Core and Builtins/2019-06-06-11-00-55.bpo-36974.wdzzym.rst
new file mode 100644
index 000000000000..035cdd3d6a9e
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2019-06-06-11-00-55.bpo-36974.wdzzym.rst	
@@ -0,0 +1,2 @@
+The slot ``tp_vectorcall_offset`` is inherited unconditionally to support
+``super().__call__()`` when the base class uses vectorcall.
diff --git a/Objects/call.c b/Objects/call.c
index 578e1b3ab619..1f41f5cb6bbf 100644
--- a/Objects/call.c
+++ b/Objects/call.c
@@ -176,7 +176,7 @@ PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwargs)
     /* get vectorcallfunc as in _PyVectorcall_Function, but without
      * the _Py_TPFLAGS_HAVE_VECTORCALL check */
     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",
                      Py_TYPE(callable)->tp_name);
         return NULL;
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 01e95aea61af..6d94bc998981 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -5148,15 +5148,15 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
     COPYSLOT(tp_repr);
     /* tp_hash see tp_richcompare */
     {
-        /* Inherit tp_vectorcall_offset only if tp_call is not overridden */
-        if (!type->tp_call) {
-            COPYSLOT(tp_vectorcall_offset);
-        }
-        /* Inherit_Py_TPFLAGS_HAVE_VECTORCALL for non-heap types
+        /* Always inherit tp_vectorcall_offset to support PyVectorcall_Call().
+         * If _Py_TPFLAGS_HAVE_VECTORCALL is not inherited, then vectorcall
+         * won't be used automatically. */
+        COPYSLOT(tp_vectorcall_offset);
+
+        /* Inherit _Py_TPFLAGS_HAVE_VECTORCALL for non-heap types
         * if tp_call is not overridden */
         if (!type->tp_call &&
             (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_HAVE_VECTORCALL;



More information about the Python-checkins mailing list