Skip to content

Commit 602024e

Browse files
bpo-46921: Vectorcall support for super() (GH-31687)
Co-Authored-By: Dong-hee Na <[email protected]>
1 parent 2d8b764 commit 602024e

File tree

3 files changed

+62
-2
lines changed

3 files changed

+62
-2
lines changed

Lib/test/test_super.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,14 @@ def test_super_init_leaks(self):
317317
for i in range(1000):
318318
super.__init__(sp, int, i)
319319

320+
def test_super_argcount(self):
321+
with self.assertRaisesRegex(TypeError, "expected at most"):
322+
super(int, int, int)
323+
324+
def test_super_argtype(self):
325+
with self.assertRaisesRegex(TypeError, "argument 1 must be a type"):
326+
super(1, int)
327+
320328

321329
if __name__ == "__main__":
322330
unittest.main()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Support vectorcall for ``super()``. Patch by Ken Jin.

Objects/typeobject.c

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9000,19 +9000,28 @@ super_init_without_args(_PyInterpreterFrame *cframe, PyCodeObject *co,
90009000
return 0;
90019001
}
90029002

9003+
static int super_init_impl(PyObject *self, PyTypeObject *type, PyObject *obj);
9004+
90039005
static int
90049006
super_init(PyObject *self, PyObject *args, PyObject *kwds)
90059007
{
9006-
superobject *su = (superobject *)self;
90079008
PyTypeObject *type = NULL;
90089009
PyObject *obj = NULL;
9009-
PyTypeObject *obj_type = NULL;
90109010

90119011
if (!_PyArg_NoKeywords("super", kwds))
90129012
return -1;
90139013
if (!PyArg_ParseTuple(args, "|O!O:super", &PyType_Type, &type, &obj))
90149014
return -1;
9015+
if (super_init_impl(self, type, obj) < 0) {
9016+
return -1;
9017+
}
9018+
return 0;
9019+
}
90159020

9021+
static inline int
9022+
super_init_impl(PyObject *self, PyTypeObject *type, PyObject *obj) {
9023+
superobject *su = (superobject *)self;
9024+
PyTypeObject *obj_type = NULL;
90169025
if (type == NULL) {
90179026
/* Call super(), without args -- fill in from __class__
90189027
and first local variable on the stack. */
@@ -9072,6 +9081,47 @@ super_traverse(PyObject *self, visitproc visit, void *arg)
90729081
return 0;
90739082
}
90749083

9084+
static PyObject *
9085+
super_vectorcall(PyObject *self, PyObject *const *args,
9086+
size_t nargsf, PyObject *kwnames)
9087+
{
9088+
assert(PyType_Check(self));
9089+
if (!_PyArg_NoKwnames("super", kwnames)) {
9090+
return NULL;
9091+
}
9092+
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
9093+
if (!_PyArg_CheckPositional("super()", nargs, 0, 2)) {
9094+
return NULL;
9095+
}
9096+
PyTypeObject *type = NULL;
9097+
PyObject *obj = NULL;
9098+
PyTypeObject *self_type = (PyTypeObject *)self;
9099+
PyObject *su = self_type->tp_alloc(self_type, 0);
9100+
if (su == NULL) {
9101+
return NULL;
9102+
}
9103+
// 1 or 2 argument form super().
9104+
if (nargs != 0) {
9105+
PyObject *arg0 = args[0];
9106+
if (!PyType_Check(arg0)) {
9107+
PyErr_Format(PyExc_TypeError,
9108+
"super() argument 1 must be a type, not %.200s", Py_TYPE(arg0)->tp_name);
9109+
goto fail;
9110+
}
9111+
type = (PyTypeObject *)arg0;
9112+
}
9113+
if (nargs == 2) {
9114+
obj = args[1];
9115+
}
9116+
if (super_init_impl(su, type, obj) < 0) {
9117+
goto fail;
9118+
}
9119+
return su;
9120+
fail:
9121+
Py_DECREF(su);
9122+
return NULL;
9123+
}
9124+
90759125
PyTypeObject PySuper_Type = {
90769126
PyVarObject_HEAD_INIT(&PyType_Type, 0)
90779127
"super", /* tp_name */
@@ -9114,4 +9164,5 @@ PyTypeObject PySuper_Type = {
91149164
PyType_GenericAlloc, /* tp_alloc */
91159165
PyType_GenericNew, /* tp_new */
91169166
PyObject_GC_Del, /* tp_free */
9167+
.tp_vectorcall = (vectorcallfunc)super_vectorcall,
91179168
};

0 commit comments

Comments
 (0)