diff --git a/Lib/test/test_super.py b/Lib/test/test_super.py index 5d94372bf6ec7f..a68b38cf79d537 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 00000000000000..4ccd00b87f591e --- /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 1dfeac3b9e660d..78795150756130 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, };