[Python-checkins] bpo-46921: Vectorcall support for `super()` (GH-31687)

Fidget-Spinner webhook-mailer at python.org
Sun Mar 6 01:22:00 EST 2022


https://github.com/python/cpython/commit/602024e6e12c69d836aa191d63db75862aec2493
commit: 602024e6e12c69d836aa191d63db75862aec2493
branch: main
author: Ken Jin <28750310+Fidget-Spinner at users.noreply.github.com>
committer: Fidget-Spinner <28750310+Fidget-Spinner at users.noreply.github.com>
date: 2022-03-06T14:21:28+08:00
summary:

bpo-46921: Vectorcall support for `super()` (GH-31687)

Co-Authored-By: Dong-hee Na <donghee.na at python.org>

files:
A Misc/NEWS.d/next/Core and Builtins/2022-03-05-00-43-22.bpo-46921.tyuPeB.rst
M Lib/test/test_super.py
M Objects/typeobject.c

diff --git a/Lib/test/test_super.py b/Lib/test/test_super.py
index 5d94372bf6ec7..a68b38cf79d53 100644
--- a/Lib/test/test_super.py
+++ b/Lib/test/test_super.py
@@ -317,6 +317,14 @@ def test_super_init_leaks(self):
         for i in range(1000):
             super.__init__(sp, int, i)
 
+    def test_super_argcount(self):
+        with self.assertRaisesRegex(TypeError, "expected at most"):
+            super(int, int, int)
+
+    def test_super_argtype(self):
+        with self.assertRaisesRegex(TypeError, "argument 1 must be a type"):
+            super(1, int)
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-03-05-00-43-22.bpo-46921.tyuPeB.rst b/Misc/NEWS.d/next/Core and Builtins/2022-03-05-00-43-22.bpo-46921.tyuPeB.rst
new file mode 100644
index 0000000000000..4ccd00b87f591
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2022-03-05-00-43-22.bpo-46921.tyuPeB.rst	
@@ -0,0 +1 @@
+Support vectorcall for ``super()``. Patch by Ken Jin.
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 1dfeac3b9e660..7879515075613 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -9000,19 +9000,28 @@ super_init_without_args(_PyInterpreterFrame *cframe, PyCodeObject *co,
     return 0;
 }
 
+static int super_init_impl(PyObject *self, PyTypeObject *type, PyObject *obj);
+
 static int
 super_init(PyObject *self, PyObject *args, PyObject *kwds)
 {
-    superobject *su = (superobject *)self;
     PyTypeObject *type = NULL;
     PyObject *obj = NULL;
-    PyTypeObject *obj_type = NULL;
 
     if (!_PyArg_NoKeywords("super", kwds))
         return -1;
     if (!PyArg_ParseTuple(args, "|O!O:super", &PyType_Type, &type, &obj))
         return -1;
+    if (super_init_impl(self, type, obj) < 0) {
+        return -1;
+    }
+    return 0;
+}
 
+static inline int
+super_init_impl(PyObject *self, PyTypeObject *type, PyObject *obj) {
+    superobject *su = (superobject *)self;
+    PyTypeObject *obj_type = NULL;
     if (type == NULL) {
         /* Call super(), without args -- fill in from __class__
            and first local variable on the stack. */
@@ -9072,6 +9081,47 @@ super_traverse(PyObject *self, visitproc visit, void *arg)
     return 0;
 }
 
+static PyObject *
+super_vectorcall(PyObject *self, PyObject *const *args,
+    size_t nargsf, PyObject *kwnames)
+{
+    assert(PyType_Check(self));
+    if (!_PyArg_NoKwnames("super", kwnames)) {
+        return NULL;
+    }
+    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
+    if (!_PyArg_CheckPositional("super()", nargs, 0, 2)) {
+        return NULL;
+    }
+    PyTypeObject *type = NULL;
+    PyObject *obj = NULL;
+    PyTypeObject *self_type = (PyTypeObject *)self;
+    PyObject *su = self_type->tp_alloc(self_type, 0);
+    if (su == NULL) {
+        return NULL;
+    }
+    // 1 or 2 argument form super().
+    if (nargs != 0) {
+        PyObject *arg0 = args[0];
+        if (!PyType_Check(arg0)) {
+            PyErr_Format(PyExc_TypeError,
+                "super() argument 1 must be a type, not %.200s", Py_TYPE(arg0)->tp_name);
+            goto fail;
+        }
+        type = (PyTypeObject *)arg0;
+    }
+    if (nargs == 2) {
+        obj = args[1];
+    }
+    if (super_init_impl(su, type, obj) < 0) {
+        goto fail;
+    }
+    return su;
+fail:
+    Py_DECREF(su);
+    return NULL;
+}
+
 PyTypeObject PySuper_Type = {
     PyVarObject_HEAD_INIT(&PyType_Type, 0)
     "super",                                    /* tp_name */
@@ -9114,4 +9164,5 @@ PyTypeObject PySuper_Type = {
     PyType_GenericAlloc,                        /* tp_alloc */
     PyType_GenericNew,                          /* tp_new */
     PyObject_GC_Del,                            /* tp_free */
+    .tp_vectorcall = (vectorcallfunc)super_vectorcall,
 };



More information about the Python-checkins mailing list