From a88ec4c9add981713576d4db6abe6015a2cd3223 Mon Sep 17 00:00:00 2001 From: Fidget-Spinner <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sat, 5 Mar 2022 00:43:38 +0800 Subject: [PATCH 1/4] vectorcall support for super() --- .../2022-03-05-00-43-22.bpo-46921.tyuPeB.rst | 1 + Objects/typeobject.c | 53 ++++++++++++++++++- 2 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-03-05-00-43-22.bpo-46921.tyuPeB.rst 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..dd07dbdc455e86 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,45 @@ 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 (kwnames != NULL) { + PyErr_SetString(PyExc_TypeError, "super() takes no keyword arguments"); + return NULL; + } + + PyTypeObject *type = NULL; + PyObject *obj = NULL; + PyTypeObject *self_type = (PyTypeObject *)self; + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + PyObject *su = self_type->tp_alloc(self_type, 0); + if (su == NULL) { + return NULL; + } + 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 +9162,5 @@ PyTypeObject PySuper_Type = { PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */ PyObject_GC_Del, /* tp_free */ + .tp_vectorcall = (vectorcallfunc)super_vectorcall, }; From 896eb363f34dab97a76286aa4b06bb4962298034 Mon Sep 17 00:00:00 2001 From: Fidget-Spinner <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sat, 5 Mar 2022 01:06:27 +0800 Subject: [PATCH 2/4] Use _PyArg_NoKwnames instead Co-Authored-By: Dong-hee Na --- Objects/typeobject.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index dd07dbdc455e86..0d223a7071ed18 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -9086,8 +9086,7 @@ super_vectorcall(PyObject *self, PyObject *const *args, size_t nargsf, PyObject *kwnames) { assert(PyType_Check(self)); - if (kwnames != NULL) { - PyErr_SetString(PyExc_TypeError, "super() takes no keyword arguments"); + if (!_PyArg_NoKwnames("super", kwnames)) { return NULL; } From 0bbe8d631ae3ee6d9628c6f784703aaa01affb97 Mon Sep 17 00:00:00 2001 From: Fidget-Spinner <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sun, 6 Mar 2022 01:16:48 +0800 Subject: [PATCH 3/4] Address code review Co-Authored-By: Dong-hee Na --- Objects/typeobject.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 0d223a7071ed18..78795150756130 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -9089,15 +9089,18 @@ super_vectorcall(PyObject *self, PyObject *const *args, 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; - Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); 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)) { From 4416fe63d907b09eb4cb672e67423bab9170a990 Mon Sep 17 00:00:00 2001 From: Fidget-Spinner <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sun, 6 Mar 2022 02:34:30 +0800 Subject: [PATCH 4/4] Add a tests --- Lib/test/test_super.py | 8 ++++++++ 1 file changed, 8 insertions(+) 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()