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

Co-Authored-By: Dong-hee Na <donghee.na@python.org>
This commit is contained in:
Ken Jin 2022-03-06 14:21:28 +08:00 committed by GitHub
parent 2d8b764210
commit 602024e6e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 2 deletions

View File

@ -317,6 +317,14 @@ class TestSuper(unittest.TestCase):
for i in range(1000): for i in range(1000):
super.__init__(sp, int, i) 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__": if __name__ == "__main__":
unittest.main() unittest.main()

View File

@ -0,0 +1 @@
Support vectorcall for ``super()``. Patch by Ken Jin.

View File

@ -9000,19 +9000,28 @@ super_init_without_args(_PyInterpreterFrame *cframe, PyCodeObject *co,
return 0; return 0;
} }
static int super_init_impl(PyObject *self, PyTypeObject *type, PyObject *obj);
static int static int
super_init(PyObject *self, PyObject *args, PyObject *kwds) super_init(PyObject *self, PyObject *args, PyObject *kwds)
{ {
superobject *su = (superobject *)self;
PyTypeObject *type = NULL; PyTypeObject *type = NULL;
PyObject *obj = NULL; PyObject *obj = NULL;
PyTypeObject *obj_type = NULL;
if (!_PyArg_NoKeywords("super", kwds)) if (!_PyArg_NoKeywords("super", kwds))
return -1; return -1;
if (!PyArg_ParseTuple(args, "|O!O:super", &PyType_Type, &type, &obj)) if (!PyArg_ParseTuple(args, "|O!O:super", &PyType_Type, &type, &obj))
return -1; 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) { if (type == NULL) {
/* Call super(), without args -- fill in from __class__ /* Call super(), without args -- fill in from __class__
and first local variable on the stack. */ and first local variable on the stack. */
@ -9072,6 +9081,47 @@ super_traverse(PyObject *self, visitproc visit, void *arg)
return 0; 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 = { PyTypeObject PySuper_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0) PyVarObject_HEAD_INIT(&PyType_Type, 0)
"super", /* tp_name */ "super", /* tp_name */
@ -9114,4 +9164,5 @@ PyTypeObject PySuper_Type = {
PyType_GenericAlloc, /* tp_alloc */ PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */ PyType_GenericNew, /* tp_new */
PyObject_GC_Del, /* tp_free */ PyObject_GC_Del, /* tp_free */
.tp_vectorcall = (vectorcallfunc)super_vectorcall,
}; };