]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-122943: Rework support of var-positional parameter in Argument Clinic (GH-122945)
authorSerhiy Storchaka <storchaka@gmail.com>
Thu, 7 Nov 2024 21:40:03 +0000 (23:40 +0200)
committerGitHub <noreply@github.com>
Thu, 7 Nov 2024 21:40:03 +0000 (23:40 +0200)
Move creation of a tuple for var-positional parameter out of
_PyArg_UnpackKeywordsWithVararg().
Merge _PyArg_UnpackKeywordsWithVararg() with _PyArg_UnpackKeywords().
Add a new parameter in _PyArg_UnpackKeywords().

The "parameters" and "converters" attributes of ParseArgsCodeGen no
longer contain the var-positional parameter. It is now available as the
"varpos" attribute. Optimize code generation for var-positional
parameter and reuse the same generating code for functions with and without
keyword parameters.

Add special converters for var-positional parameter. "tuple" represents it as
a Python tuple and "array" represents it as a continuous array of PyObject*.
"object" is a temporary alias of "tuple".

22 files changed:
Include/internal/pycore_modsupport.h
Include/internal/pycore_tuple.h
Lib/test/clinic.test.c
Lib/test/test_clinic.py
Modules/_testclinic.c
Modules/clinic/_testclinic.c.h
Modules/clinic/_testclinic_depr.c.h
Modules/clinic/gcmodule.c.h
Modules/clinic/mathmodule.c.h
Modules/gcmodule.c
Modules/mathmodule.c
Objects/clinic/setobject.c.h
Objects/clinic/typevarobject.c.h
Objects/setobject.c
Python/clinic/bltinmodule.c.h
Python/getargs.c
Tools/c-analyzer/c_parser/parser/__init__.py
Tools/clinic/libclinic/clanguage.py
Tools/clinic/libclinic/converter.py
Tools/clinic/libclinic/converters.py
Tools/clinic/libclinic/dsl_parser.py
Tools/clinic/libclinic/parse_args.py

index 11fde814875938f23768d517a5434032502b9298..250106ad83a3ecb6b1acb0e9b4eae7939a79a1d2 100644 (file)
@@ -76,7 +76,7 @@ PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords(
     ...);
 
 // Export for 'math' shared extension
-PyAPI_FUNC(PyObject * const *) _PyArg_UnpackKeywords(
+PyAPI_FUNC(PyObject * const *) _PyArg_UnpackKeywordsEx(
     PyObject *const *args,
     Py_ssize_t nargs,
     PyObject *kwargs,
@@ -85,20 +85,19 @@ PyAPI_FUNC(PyObject * const *) _PyArg_UnpackKeywords(
     int minpos,
     int maxpos,
     int minkw,
+    int varpos,
     PyObject **buf);
 #define _PyArg_UnpackKeywords(args, nargs, kwargs, kwnames, parser, minpos, maxpos, minkw, buf) \
     (((minkw) == 0 && (kwargs) == NULL && (kwnames) == NULL && \
-      (minpos) <= (nargs) && (nargs) <= (maxpos) && (args) != NULL) ? (args) : \
-     _PyArg_UnpackKeywords((args), (nargs), (kwargs), (kwnames), (parser), \
-                           (minpos), (maxpos), (minkw), (buf)))
-
-// Export for '_testclinic' shared extension
-PyAPI_FUNC(PyObject * const *) _PyArg_UnpackKeywordsWithVararg(
-        PyObject *const *args, Py_ssize_t nargs,
-        PyObject *kwargs, PyObject *kwnames,
-        struct _PyArg_Parser *parser,
-        int minpos, int maxpos, int minkw,
-        int vararg, PyObject **buf);
+      (minpos) <= (nargs) && (nargs) <= (maxpos) && (args) != NULL) ? \
+      (args) : \
+     _PyArg_UnpackKeywordsEx((args), (nargs), (kwargs), (kwnames), (parser), \
+                           (minpos), (maxpos), (minkw), 0, (buf)))
+#define _PyArg_UnpackKeywordsWithVararg(args, nargs, kwargs, kwnames, parser, minpos, maxpos, minkw, buf) \
+    (((minkw) == 0 && (kwargs) == NULL && (kwnames) == NULL && \
+      (minpos) <= (nargs) && (args) != NULL) ? (args) : \
+     _PyArg_UnpackKeywordsEx((args), (nargs), (kwargs), (kwnames), (parser), \
+                           (minpos), (maxpos), (minkw), 1, (buf)))
 
 #ifdef __cplusplus
 }
index dfbbd6fd0c7de563c0a961ca5705568b376eda88..82b875241f4116f9fb941eccc763cb1d67a9376e 100644 (file)
@@ -20,7 +20,7 @@ extern PyStatus _PyTuple_InitGlobalObjects(PyInterpreterState *);
 
 #define _PyTuple_ITEMS(op) _Py_RVALUE(_PyTuple_CAST(op)->ob_item)
 
-extern PyObject *_PyTuple_FromArray(PyObject *const *, Py_ssize_t);
+PyAPI_FUNC(PyObject *)_PyTuple_FromArray(PyObject *const *, Py_ssize_t);
 PyAPI_FUNC(PyObject *)_PyTuple_FromStackRefSteal(const union _PyStackRef *, Py_ssize_t);
 PyAPI_FUNC(PyObject *)_PyTuple_FromArraySteal(PyObject *const *, Py_ssize_t);
 
index e22324efc490bec11027d552658071cd8c7b1209..80208862f2a09a3875542e919000a3cfd7ada4ab 100644 (file)
@@ -4144,6 +4144,45 @@ PyDoc_STRVAR(test_vararg_and_posonly__doc__,
 "--\n"
 "\n");
 
+#define TEST_VARARG_AND_POSONLY_METHODDEF    \
+    {"test_vararg_and_posonly", _PyCFunction_CAST(test_vararg_and_posonly), METH_FASTCALL, test_vararg_and_posonly__doc__},
+
+static PyObject *
+test_vararg_and_posonly_impl(PyObject *module, PyObject *a, PyObject *args);
+
+static PyObject *
+test_vararg_and_posonly(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject *a;
+    PyObject *__clinic_args = NULL;
+
+    if (!_PyArg_CheckPositional("test_vararg_and_posonly", nargs, 1, PY_SSIZE_T_MAX)) {
+        goto exit;
+    }
+    a = args[0];
+    __clinic_args = _PyTuple_FromArray(args + 1, nargs - 1);
+    if (__clinic_args == NULL) {
+        goto exit;
+    }
+    return_value = test_vararg_and_posonly_impl(module, a, __clinic_args);
+
+exit:
+    /* Cleanup for args */
+    Py_XDECREF(__clinic_args);
+
+    return return_value;
+}
+
+static PyObject *
+test_vararg_and_posonly_impl(PyObject *module, PyObject *a, PyObject *args)
+/*[clinic end generated code: output=0c11c475e240869e input=9cfa748bbff09877]*/
+
+PyDoc_STRVAR(test_vararg_and_posonly__doc__,
+"test_vararg_and_posonly($module, a, /, *args)\n"
+"--\n"
+"\n");
+
 #define TEST_VARARG_AND_POSONLY_METHODDEF    \
     {"test_vararg_and_posonly", _PyCFunction_CAST(test_vararg_and_posonly), METH_FASTCALL, test_vararg_and_posonly__doc__},
 
@@ -4163,17 +4202,19 @@ test_vararg_and_posonly(PyObject *module, PyObject *const *args, Py_ssize_t narg
         goto exit;
     }
     a = args[0];
-    __clinic_args = args + 1;
+    __clinic_args = _PyTuple_FromArray(args + 1, nargs - 1);
+    if (__clinic_args == NULL) {
+        goto exit;
+    }
     return_value = test_vararg_and_posonly_impl(module, a, nvararg, __clinic_args);
 
 exit:
+    /* Cleanup for args */
+    Py_XDECREF(__clinic_args);
+
     return return_value;
 }
 
-static PyObject *
-test_vararg_and_posonly_impl(PyObject *module, PyObject *a, Py_ssize_t nargs,
-                             PyObject *const *args)
-/*[clinic end generated code: output=dc2dd9483cc0459e input=9cfa748bbff09877]*/
 
 /*[clinic input]
 test_vararg
@@ -4224,26 +4265,34 @@ test_vararg(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
         .kwtuple = KWTUPLE,
     };
     #undef KWTUPLE
-    PyObject *argsbuf[2];
+    PyObject *argsbuf[1];
+    PyObject * const *fastargs;
     PyObject *a;
     PyObject *__clinic_args = NULL;
 
-    args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf);
-    if (!args) {
+    fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+    if (!fastargs) {
+        goto exit;
+    }
+    a = fastargs[0];
+    __clinic_args = nargs > 1
+        ? _PyTuple_FromArray(args + 1, nargs - 1)
+        : PyTuple_New(0);
+    if (__clinic_args == NULL) {
         goto exit;
     }
-    a = args[0];
-    __clinic_args = args[1];
     return_value = test_vararg_impl(module, a, __clinic_args);
 
 exit:
+    /* Cleanup for args */
     Py_XDECREF(__clinic_args);
+
     return return_value;
 }
 
 static PyObject *
 test_vararg_impl(PyObject *module, PyObject *a, PyObject *args)
-/*[clinic end generated code: output=1411e464f358a7ba input=81d33815ad1bae6e]*/
+/*[clinic end generated code: output=e7d7da6a7e008125 input=81d33815ad1bae6e]*/
 
 /*[clinic input]
 test_vararg_with_default
@@ -4296,37 +4345,45 @@ test_vararg_with_default(PyObject *module, PyObject *const *args, Py_ssize_t nar
         .kwtuple = KWTUPLE,
     };
     #undef KWTUPLE
-    PyObject *argsbuf[3];
+    PyObject *argsbuf[2];
+    PyObject * const *fastargs;
     Py_ssize_t noptargs = Py_MIN(nargs, 1) + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
     PyObject *a;
     PyObject *__clinic_args = NULL;
     int b = 0;
 
-    args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf);
-    if (!args) {
+    fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+    if (!fastargs) {
         goto exit;
     }
-    a = args[0];
-    __clinic_args = args[1];
+    a = fastargs[0];
     if (!noptargs) {
         goto skip_optional_kwonly;
     }
-    b = PyObject_IsTrue(args[2]);
+    b = PyObject_IsTrue(fastargs[1]);
     if (b < 0) {
         goto exit;
     }
 skip_optional_kwonly:
+    __clinic_args = nargs > 1
+        ? _PyTuple_FromArray(args + 1, nargs - 1)
+        : PyTuple_New(0);
+    if (__clinic_args == NULL) {
+        goto exit;
+    }
     return_value = test_vararg_with_default_impl(module, a, __clinic_args, b);
 
 exit:
+    /* Cleanup for args */
     Py_XDECREF(__clinic_args);
+
     return return_value;
 }
 
 static PyObject *
 test_vararg_with_default_impl(PyObject *module, PyObject *a, PyObject *args,
                               int b)
-/*[clinic end generated code: output=f09d4b917063ca41 input=6e110b54acd9b22d]*/
+/*[clinic end generated code: output=46781f9920ecedcf input=6e110b54acd9b22d]*/
 
 /*[clinic input]
 test_vararg_with_only_defaults
@@ -4379,22 +4436,22 @@ test_vararg_with_only_defaults(PyObject *module, PyObject *const *args, Py_ssize
         .kwtuple = KWTUPLE,
     };
     #undef KWTUPLE
-    PyObject *argsbuf[3];
+    PyObject *argsbuf[2];
+    PyObject * const *fastargs;
     Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
     PyObject *__clinic_args = NULL;
     int b = 0;
     PyObject *c = " ";
 
-    args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, 0, argsbuf);
-    if (!args) {
+    fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf);
+    if (!fastargs) {
         goto exit;
     }
-    __clinic_args = args[0];
     if (!noptargs) {
         goto skip_optional_kwonly;
     }
-    if (args[1]) {
-        b = PyObject_IsTrue(args[1]);
+    if (fastargs[0]) {
+        b = PyObject_IsTrue(fastargs[0]);
         if (b < 0) {
             goto exit;
         }
@@ -4402,19 +4459,25 @@ test_vararg_with_only_defaults(PyObject *module, PyObject *const *args, Py_ssize
             goto skip_optional_kwonly;
         }
     }
-    c = args[2];
+    c = fastargs[1];
 skip_optional_kwonly:
+    __clinic_args = _PyTuple_FromArray(args, nargs);
+    if (__clinic_args == NULL) {
+        goto exit;
+    }
     return_value = test_vararg_with_only_defaults_impl(module, __clinic_args, b, c);
 
 exit:
+    /* Cleanup for args */
     Py_XDECREF(__clinic_args);
+
     return return_value;
 }
 
 static PyObject *
 test_vararg_with_only_defaults_impl(PyObject *module, PyObject *args, int b,
                                     PyObject *c)
-/*[clinic end generated code: output=cc6590b8805d5433 input=fa56a709a035666e]*/
+/*[clinic end generated code: output=d03daf5067039c03 input=fa56a709a035666e]*/
 
 /*[clinic input]
 test_paramname_module
@@ -4927,33 +4990,65 @@ PyDoc_STRVAR(Test___init____doc__,
 "Varargs init method. For example, nargs is translated to PyTuple_GET_SIZE.");
 
 static int
-Test___init___impl(TestObj *self, Py_ssize_t nargs, PyObject *const *args);
+Test___init___impl(TestObj *self, PyObject *args);
 
 static int
 Test___init__(PyObject *self, PyObject *args, PyObject *kwargs)
 {
     int return_value = -1;
     PyTypeObject *base_tp = TestType;
-    PyObject *const *__clinic_args = NULL;
+    PyObject *__clinic_args = NULL;
 
     if ((Py_IS_TYPE(self, base_tp) ||
          Py_TYPE(self)->tp_new == base_tp->tp_new) &&
         !_PyArg_NoKeywords("Test", kwargs)) {
         goto exit;
     }
-    if (!_PyArg_CheckPositional("Test", PyTuple_GET_SIZE(args), 0, PY_SSIZE_T_MAX)) {
+    __clinic_args = Py_NewRef(args);
+    return_value = Test___init___impl((TestObj *)self, __clinic_args);
+
+exit:
+    /* Cleanup for args */
+    Py_XDECREF(__clinic_args);
+
+    return return_value;
+}
+
+static int
+Test___init___impl(TestObj *self, PyObject *args)
+/*[clinic end generated code: output=f172425cec373cd6 input=2a8bd0033c9ac772]*/
+
+PyDoc_STRVAR(Test___init____doc__,
+"Test(*args)\n"
+"--\n"
+"\n"
+"Varargs init method. For example, nargs is translated to PyTuple_GET_SIZE.");
+
+static int
+Test___init___impl(TestObj *self, Py_ssize_t nargs, PyObject *const *args);
+
+static int
+Test___init__(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    int return_value = -1;
+    PyTypeObject *base_tp = TestType;
+    PyObject *const *__clinic_args = NULL;
+
+    if ((Py_IS_TYPE(self, base_tp) ||
+         Py_TYPE(self)->tp_new == base_tp->tp_new) &&
+        !_PyArg_NoKeywords("Test", kwargs)) {
         goto exit;
     }
-    __clinic_args = _PyTuple_CAST(args)->ob_item;
+    __clinic_args = Py_NewRef(args);
     return_value = Test___init___impl((TestObj *)self, nvararg, __clinic_args);
 
 exit:
+    /* Cleanup for args */
+    Py_XDECREF(__clinic_args);
+
     return return_value;
 }
 
-static int
-Test___init___impl(TestObj *self, Py_ssize_t nargs, PyObject *const *args)
-/*[clinic end generated code: output=6a64b417c9080a73 input=2a8bd0033c9ac772]*/
 
 
 /*[clinic input]
@@ -4971,32 +5066,63 @@ PyDoc_STRVAR(Test__doc__,
 "Varargs new method. For example, nargs is translated to PyTuple_GET_SIZE.");
 
 static PyObject *
-Test_impl(PyTypeObject *type, Py_ssize_t nargs, PyObject *const *args);
+Test_impl(PyTypeObject *type, PyObject *args);
 
 static PyObject *
 Test(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
     PyTypeObject *base_tp = TestType;
-    PyObject *const *__clinic_args = NULL;
+    PyObject *__clinic_args = NULL;
 
     if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
         !_PyArg_NoKeywords("Test", kwargs)) {
         goto exit;
     }
-    if (!_PyArg_CheckPositional("Test", PyTuple_GET_SIZE(args), 0, PY_SSIZE_T_MAX)) {
+    __clinic_args = Py_NewRef(args);
+    return_value = Test_impl(type, __clinic_args);
+
+exit:
+    /* Cleanup for args */
+    Py_XDECREF(__clinic_args);
+
+    return return_value;
+}
+
+static PyObject *
+Test_impl(PyTypeObject *type, PyObject *args)
+/*[clinic end generated code: output=ee1e8892a67abd4a input=70ad829df3dd9b84]*/
+
+PyDoc_STRVAR(Test__doc__,
+"Test(*args)\n"
+"--\n"
+"\n"
+"Varargs new method. For example, nargs is translated to PyTuple_GET_SIZE.");
+
+static PyObject *
+Test_impl(PyTypeObject *type, Py_ssize_t nargs, PyObject *const *args);
+
+static PyObject *
+Test(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    PyTypeObject *base_tp = TestType;
+    PyObject *const *__clinic_args = NULL;
+
+    if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
+        !_PyArg_NoKeywords("Test", kwargs)) {
         goto exit;
     }
-    __clinic_args = _PyTuple_CAST(args)->ob_item;
+    __clinic_args = Py_NewRef(args);
     return_value = Test_impl(type, nvararg, __clinic_args);
 
 exit:
+    /* Cleanup for args */
+    Py_XDECREF(__clinic_args);
+
     return return_value;
 }
 
-static PyObject *
-Test_impl(PyTypeObject *type, Py_ssize_t nargs, PyObject *const *args)
-/*[clinic end generated code: output=bf22f942407383a5 input=70ad829df3dd9b84]*/
 
 
 /*[clinic input]
index d492ea1d76aa3ad20fb17080797830ac02ab80e1..a4317a3ad468d8e98eb31d7fc04d834bf57c5ead 100644 (file)
@@ -33,6 +33,15 @@ with test_tools.imports_under_tool('clinic'):
     from libclinic.cli import parse_file, Clinic
 
 
+def repeat_fn(*functions):
+    def wrapper(test):
+        def wrapped(self):
+            for fn in functions:
+                with self.subTest(fn=fn):
+                    test(self, fn)
+        return wrapped
+    return wrapper
+
 def _make_clinic(*, filename='clinic_tests', limited_capi=False):
     clang = CLanguage(filename)
     c = Clinic(clang, filename=filename, limited_capi=limited_capi)
@@ -3378,30 +3387,53 @@ class ClinicFunctionalTest(unittest.TestCase):
             ac_tester.keyword_only_parameter(1)
         self.assertEqual(ac_tester.keyword_only_parameter(a=1), (1,))
 
-    def test_varpos(self):
-        # fn(*args)
-        fn = ac_tester.varpos
-        self.assertEqual(fn(), ((),))
-        self.assertEqual(fn(1, 2), ((1, 2),))
-
-    def test_posonly_varpos(self):
-        # fn(a, b, /, *args)
-        fn = ac_tester.posonly_varpos
-        self.assertRaises(TypeError, fn)
-        self.assertRaises(TypeError, fn, 1)
-        self.assertRaises(TypeError, fn, 1, b=2)
-        self.assertEqual(fn(1, 2), (1, 2, ()))
-        self.assertEqual(fn(1, 2, 3, 4), (1, 2, (3, 4)))
-
-    def test_posonly_poskw_varpos(self):
-        # fn(a, /, b, *args)
-        fn = ac_tester.posonly_poskw_varpos
-        self.assertRaises(TypeError, fn)
-        self.assertEqual(fn(1, 2), (1, 2, ()))
-        self.assertEqual(fn(1, b=2), (1, 2, ()))
-        self.assertEqual(fn(1, 2, 3, 4), (1, 2, (3, 4)))
-        self.assertRaises(TypeError, fn, b=4)
-        self.assertRaises(TypeError, fn, 1, 2, 3, b=4)
+    if ac_tester is not None:
+        @repeat_fn(ac_tester.varpos,
+                   ac_tester.varpos_array,
+                   ac_tester.TestClass.varpos_no_fastcall,
+                   ac_tester.TestClass.varpos_array_no_fastcall)
+        def test_varpos(self, fn):
+            # fn(*args)
+            self.assertEqual(fn(), ())
+            self.assertEqual(fn(1, 2), (1, 2))
+
+        @repeat_fn(ac_tester.posonly_varpos,
+                   ac_tester.posonly_varpos_array,
+                   ac_tester.TestClass.posonly_varpos_no_fastcall,
+                   ac_tester.TestClass.posonly_varpos_array_no_fastcall)
+        def test_posonly_varpos(self, fn):
+            # fn(a, b, /, *args)
+            self.assertRaises(TypeError, fn)
+            self.assertRaises(TypeError, fn, 1)
+            self.assertRaises(TypeError, fn, 1, b=2)
+            self.assertEqual(fn(1, 2), (1, 2, ()))
+            self.assertEqual(fn(1, 2, 3, 4), (1, 2, (3, 4)))
+
+        @repeat_fn(ac_tester.posonly_req_opt_varpos,
+                   ac_tester.posonly_req_opt_varpos_array,
+                   ac_tester.TestClass.posonly_req_opt_varpos_no_fastcall,
+                   ac_tester.TestClass.posonly_req_opt_varpos_array_no_fastcall)
+        def test_posonly_req_opt_varpos(self, fn):
+            # fn(a, b=False, /, *args)
+            self.assertRaises(TypeError, fn)
+            self.assertRaises(TypeError, fn, a=1)
+            self.assertEqual(fn(1), (1, False, ()))
+            self.assertEqual(fn(1, 2), (1, 2, ()))
+            self.assertEqual(fn(1, 2, 3, 4), (1, 2, (3, 4)))
+
+        @repeat_fn(ac_tester.posonly_poskw_varpos,
+                   ac_tester.posonly_poskw_varpos_array,
+                   ac_tester.TestClass.posonly_poskw_varpos_no_fastcall,
+                   ac_tester.TestClass.posonly_poskw_varpos_array_no_fastcall)
+        def test_posonly_poskw_varpos(self, fn):
+            # fn(a, /, b, *args)
+            self.assertRaises(TypeError, fn)
+            self.assertEqual(fn(1, 2), (1, 2, ()))
+            self.assertEqual(fn(1, b=2), (1, 2, ()))
+            self.assertEqual(fn(1, 2, 3, 4), (1, 2, (3, 4)))
+            self.assertRaises(TypeError, fn, b=4)
+            errmsg = re.escape("given by name ('b') and position (2)")
+            self.assertRaisesRegex(TypeError, errmsg, fn, 1, 2, 3, b=4)
 
     def test_poskw_varpos(self):
         # fn(a, *args)
@@ -3409,7 +3441,8 @@ class ClinicFunctionalTest(unittest.TestCase):
         self.assertRaises(TypeError, fn)
         self.assertRaises(TypeError, fn, 1, b=2)
         self.assertEqual(fn(a=1), (1, ()))
-        self.assertRaises(TypeError, fn, 1, a=2)
+        errmsg = re.escape("given by name ('a') and position (1)")
+        self.assertRaisesRegex(TypeError, errmsg, fn, 1, a=2)
         self.assertEqual(fn(1), (1, ()))
         self.assertEqual(fn(1, 2, 3, 4), (1, (2, 3, 4)))
 
@@ -3417,7 +3450,8 @@ class ClinicFunctionalTest(unittest.TestCase):
         # fn(a, *args, b=False)
         fn = ac_tester.poskw_varpos_kwonly_opt
         self.assertRaises(TypeError, fn)
-        self.assertRaises(TypeError, fn, 1, a=2)
+        errmsg = re.escape("given by name ('a') and position (1)")
+        self.assertRaisesRegex(TypeError, errmsg, fn, 1, a=2)
         self.assertEqual(fn(1, b=2), (1, (), True))
         self.assertEqual(fn(1, 2, 3, 4), (1, (2, 3, 4), False))
         self.assertEqual(fn(1, 2, 3, 4, b=5), (1, (2, 3, 4), True))
@@ -3428,7 +3462,8 @@ class ClinicFunctionalTest(unittest.TestCase):
         # fn(a, *args, b=False, c=False)
         fn = ac_tester.poskw_varpos_kwonly_opt2
         self.assertRaises(TypeError, fn)
-        self.assertRaises(TypeError, fn, 1, a=2)
+        errmsg = re.escape("given by name ('a') and position (1)")
+        self.assertRaisesRegex(TypeError, errmsg, fn, 1, a=2)
         self.assertEqual(fn(1, b=2), (1, (), 2, False))
         self.assertEqual(fn(1, b=2, c=3), (1, (), 2, 3))
         self.assertEqual(fn(1, 2, 3), (1, (2, 3), False, False))
@@ -3490,9 +3525,10 @@ class ClinicFunctionalTest(unittest.TestCase):
         self.assertEqual(fn(covariant=True, name='a'), ('a', (), True))
 
         self.assertRaises(TypeError, fn, covariant=True)
-        self.assertRaises(TypeError, fn, 1, name='a')
-        self.assertRaises(TypeError, fn, 1, 2, 3, name='a', covariant=True)
-        self.assertRaises(TypeError, fn, 1, 2, 3, covariant=True, name='a')
+        errmsg = re.escape("given by name ('name') and position (1)")
+        self.assertRaisesRegex(TypeError, errmsg, fn, 1, name='a')
+        self.assertRaisesRegex(TypeError, errmsg, fn, 1, 2, 3, name='a', covariant=True)
+        self.assertRaisesRegex(TypeError, errmsg, fn, 1, 2, 3, covariant=True, name='a')
 
     def test_cloned_func_exception_message(self):
         incorrect_arg = -1  # f1() and f2() accept a single str
@@ -3568,14 +3604,15 @@ class ClinicFunctionalTest(unittest.TestCase):
         cls = ac_tester.TestClass
         obj = cls()
         fn = obj.defclass_posonly_varpos
-        self.assertRaises(TypeError, fn)
-        self.assertRaises(TypeError, fn, 1)
+        errmsg = 'takes at least 2 positional arguments'
+        self.assertRaisesRegex(TypeError, errmsg, fn)
+        self.assertRaisesRegex(TypeError, errmsg, fn, 1)
         self.assertEqual(fn(1, 2), (cls, 1, 2, ()))
         self.assertEqual(fn(1, 2, 3, 4), (cls, 1, 2, (3, 4)))
         fn = cls.defclass_posonly_varpos
         self.assertRaises(TypeError, fn)
-        self.assertRaises(TypeError, fn, obj)
-        self.assertRaises(TypeError, fn, obj, 1)
+        self.assertRaisesRegex(TypeError, errmsg, fn, obj)
+        self.assertRaisesRegex(TypeError, errmsg, fn, obj, 1)
         self.assertEqual(fn(obj, 1, 2), (cls, 1, 2, ()))
         self.assertEqual(fn(obj, 1, 2, 3, 4), (cls, 1, 2, (3, 4)))
 
index e3c8ba9b0b5074e6d209127c674c28b5f87b1e5b..320c8ddf214dcd131b98a6a22846baccc8769aba 100644 (file)
@@ -59,19 +59,20 @@ pack_arguments_newref(int argc, ...)
 }
 
 static PyObject *
-pack_varargs_to_tuple(Py_ssize_t varargssize, PyObject *const *args)
+pack_arguments_2pos_varpos(PyObject *a, PyObject *b,
+                           PyObject * const *args, Py_ssize_t args_length)
+/*[clinic end generated code: output=267032f41bd039cc input=86ee3064b7853e86]*/
 {
-    assert(!PyErr_Occurred());
-    PyObject *tuple = PyTuple_New(varargssize);
-    if (!tuple) {
+    PyObject *tuple = _PyTuple_FromArray(args, args_length);
+    if (tuple == NULL) {
         return NULL;
     }
-    for (Py_ssize_t i = 0; i < varargssize; i++) {
-        PyTuple_SET_ITEM(tuple, i, Py_NewRef(args[i]));
-    }
-    return tuple;
+    PyObject *result = pack_arguments_newref(3, a, b, tuple);
+    Py_DECREF(tuple);
+    return result;
 }
 
+
 /* Pack arguments to a tuple.
  * `wrapper` is function which converts primitive type to PyObject.
  * `arg_type` is type that arguments should be converted to before wrapped. */
@@ -984,16 +985,10 @@ varpos
 [clinic start generated code]*/
 
 static PyObject *
-varpos_impl(PyObject *module, Py_ssize_t nargs, PyObject *const *args)
-/*[clinic end generated code: output=b65096f423fb5dcc input=f87cd674145d394c]*/
+varpos_impl(PyObject *module, PyObject *args)
+/*[clinic end generated code: output=7b0b9545872bdca4 input=f87cd674145d394c]*/
 {
-    PyObject *vararg_tuple = pack_varargs_to_tuple(nargs, args);
-    if (!vararg_tuple) {
-        return NULL;
-    }
-    PyObject *result =  pack_arguments_newref(1, vararg_tuple);
-    Py_DECREF(vararg_tuple);
-    return result;
+    return Py_NewRef(args);
 }
 
 
@@ -1009,16 +1004,29 @@ posonly_varpos
 
 static PyObject *
 posonly_varpos_impl(PyObject *module, PyObject *a, PyObject *b,
-                    Py_ssize_t nargs, PyObject *const *args)
-/*[clinic end generated code: output=d10d43d86d117ab3 input=c9fd7895cfbaabba]*/
+                    PyObject *args)
+/*[clinic end generated code: output=5dae5eb2a0d623cd input=c9fd7895cfbaabba]*/
 {
-    PyObject *vararg_tuple = pack_varargs_to_tuple(nargs, args);
-    if (!vararg_tuple) {
-        return NULL;
-    }
-    PyObject *result = pack_arguments_newref(3, a, b, vararg_tuple);
-    Py_DECREF(vararg_tuple);
-    return result;
+    return pack_arguments_newref(3, a, b, args);
+}
+
+
+/*[clinic input]
+posonly_req_opt_varpos
+
+    a: object
+    b: object = False
+    /
+    *args: object
+
+[clinic start generated code]*/
+
+static PyObject *
+posonly_req_opt_varpos_impl(PyObject *module, PyObject *a, PyObject *b,
+                            PyObject *args)
+/*[clinic end generated code: output=67f82f90838e166a input=a49bd64740171e1c]*/
+{
+    return pack_arguments_newref(3, a, b, args);
 }
 
 
@@ -1130,6 +1138,81 @@ varpos_kwonly_req_opt_impl(PyObject *module, PyObject *args, PyObject *a,
 }
 
 
+/*[clinic input]
+varpos_array
+
+    *args: array
+
+[clinic start generated code]*/
+
+static PyObject *
+varpos_array_impl(PyObject *module, PyObject * const *args,
+                  Py_ssize_t args_length)
+/*[clinic end generated code: output=a25f42f39c9b13ad input=97b8bdcf87e019c7]*/
+{
+    return _PyTuple_FromArray(args, args_length);
+}
+
+
+/*[clinic input]
+posonly_varpos_array
+
+    a: object
+    b: object
+    /
+    *args: array
+
+[clinic start generated code]*/
+
+static PyObject *
+posonly_varpos_array_impl(PyObject *module, PyObject *a, PyObject *b,
+                          PyObject * const *args, Py_ssize_t args_length)
+/*[clinic end generated code: output=267032f41bd039cc input=86ee3064b7853e86]*/
+{
+    return pack_arguments_2pos_varpos(a, b, args, args_length);
+}
+
+
+/*[clinic input]
+posonly_req_opt_varpos_array
+
+    a: object
+    b: object = False
+    /
+    *args: array
+
+[clinic start generated code]*/
+
+static PyObject *
+posonly_req_opt_varpos_array_impl(PyObject *module, PyObject *a, PyObject *b,
+                                  PyObject * const *args,
+                                  Py_ssize_t args_length)
+/*[clinic end generated code: output=f2f93c77ead93699 input=b01d7728164fd93e]*/
+{
+    return pack_arguments_2pos_varpos(a, b, args, args_length);
+}
+
+
+/*[clinic input]
+posonly_poskw_varpos_array
+
+    a: object
+    /
+    b: object
+    *args: array
+
+[clinic start generated code]*/
+
+static PyObject *
+posonly_poskw_varpos_array_impl(PyObject *module, PyObject *a, PyObject *b,
+                                PyObject * const *args,
+                                Py_ssize_t args_length)
+/*[clinic end generated code: output=155811a8b2d65a12 input=5fb08cdc6afb9d7c]*/
+{
+    return pack_arguments_2pos_varpos(a, b, args, args_length);
+}
+
+
 
 /*[clinic input]
 gh_32092_oob
@@ -1183,9 +1266,8 @@ Proof-of-concept of GH-99233 refcount error bug.
 [clinic start generated code]*/
 
 static PyObject *
-gh_99233_refcount_impl(PyObject *module, Py_ssize_t nargs,
-                       PyObject *const *args)
-/*[clinic end generated code: output=b570007e61e5c670 input=eecfdc2092d90dc3]*/
+gh_99233_refcount_impl(PyObject *module, PyObject *args)
+/*[clinic end generated code: output=585855abfbca9a7f input=eecfdc2092d90dc3]*/
 {
     Py_RETURN_NONE;
 }
@@ -1295,9 +1377,9 @@ clone_with_conv_f2_impl(PyObject *module, custom_t path)
 
 
 /*[clinic input]
-class _testclinic.TestClass "PyObject *" "PyObject"
+class _testclinic.TestClass "PyObject *" "&PyBaseObject_Type"
 [clinic start generated code]*/
-/*[clinic end generated code: output=da39a3ee5e6b4b0d input=668a591c65bec947]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c991635bb3c91f1a]*/
 
 /*[clinic input]
 _testclinic.TestClass.get_defining_class
@@ -1360,11 +1442,192 @@ _testclinic_TestClass_defclass_posonly_varpos_impl(PyObject *self,
     return pack_arguments_newref(4, cls, a, b, args);
 }
 
+
+/*[clinic input]
+@classmethod
+_testclinic.TestClass.__new__ as varpos_no_fastcall
+
+    *args: object
+
+[clinic start generated code]*/
+
+static PyObject *
+varpos_no_fastcall_impl(PyTypeObject *type, PyObject *args)
+/*[clinic end generated code: output=04e94f2898bb2dde input=b0447ebab3e81001]*/
+{
+    return Py_NewRef(args);
+}
+
+
+/*[clinic input]
+@classmethod
+_testclinic.TestClass.__new__ as posonly_varpos_no_fastcall
+
+    a: object
+    b: object
+    /
+    *args: object
+
+[clinic start generated code]*/
+
+static PyObject *
+posonly_varpos_no_fastcall_impl(PyTypeObject *type, PyObject *a, PyObject *b,
+                                PyObject *args)
+/*[clinic end generated code: output=b0a0425719f69f5a input=d2ec37a06b3c2389]*/
+{
+    return pack_arguments_newref(3, a, b, args);
+}
+
+
+/*[clinic input]
+@classmethod
+_testclinic.TestClass.__new__ as posonly_req_opt_varpos_no_fastcall
+
+    a: object
+    b: object = False
+    /
+    *args: object
+
+[clinic start generated code]*/
+
+static PyObject *
+posonly_req_opt_varpos_no_fastcall_impl(PyTypeObject *type, PyObject *a,
+                                        PyObject *b, PyObject *args)
+/*[clinic end generated code: output=3c44915b1a554e2d input=e9e74686a5e6a06d]*/
+{
+    return pack_arguments_newref(3, a, b, args);
+}
+
+
+/*[clinic input]
+@classmethod
+_testclinic.TestClass.__new__ as posonly_poskw_varpos_no_fastcall
+
+    a: object
+    /
+    b: object
+    *args: object
+
+[clinic start generated code]*/
+
+static PyObject *
+posonly_poskw_varpos_no_fastcall_impl(PyTypeObject *type, PyObject *a,
+                                      PyObject *b, PyObject *args)
+/*[clinic end generated code: output=6ad74bed4bdc7f96 input=fa931c38184213aa]*/
+{
+    return pack_arguments_newref(3, a, b, args);
+}
+
+
+/*[clinic input]
+@classmethod
+_testclinic.TestClass.__new__ as varpos_array_no_fastcall
+
+    *args: array
+
+[clinic start generated code]*/
+
+static PyObject *
+varpos_array_no_fastcall_impl(PyTypeObject *type, PyObject * const *args,
+                              Py_ssize_t args_length)
+/*[clinic end generated code: output=f99d984346c60d42 input=368d8eea6de48c12]*/
+{
+    return _PyTuple_FromArray(args, args_length);
+}
+
+
+/*[clinic input]
+@classmethod
+_testclinic.TestClass.__new__ as posonly_varpos_array_no_fastcall
+
+    a: object
+    b: object
+    /
+    *args: array
+
+[clinic start generated code]*/
+
+static PyObject *
+posonly_varpos_array_no_fastcall_impl(PyTypeObject *type, PyObject *a,
+                                      PyObject *b, PyObject * const *args,
+                                      Py_ssize_t args_length)
+/*[clinic end generated code: output=1eec4da1fb5b5978 input=7330c8d819a23548]*/
+{
+    return pack_arguments_2pos_varpos(a, b, args, args_length);
+}
+
+
+/*[clinic input]
+@classmethod
+_testclinic.TestClass.__new__ as posonly_req_opt_varpos_array_no_fastcall
+
+    a: object
+    b: object = False
+    /
+    *args: array
+
+[clinic start generated code]*/
+
+static PyObject *
+posonly_req_opt_varpos_array_no_fastcall_impl(PyTypeObject *type,
+                                              PyObject *a, PyObject *b,
+                                              PyObject * const *args,
+                                              Py_ssize_t args_length)
+/*[clinic end generated code: output=88041c2176135218 input=7f5fd34ee5f9e0bf]*/
+{
+    return pack_arguments_2pos_varpos(a, b, args, args_length);
+}
+
+
+/*[clinic input]
+@classmethod
+_testclinic.TestClass.__new__ as posonly_poskw_varpos_array_no_fastcall
+
+    a: object
+    /
+    b: object
+    *args: array
+
+[clinic start generated code]*/
+
+static PyObject *
+posonly_poskw_varpos_array_no_fastcall_impl(PyTypeObject *type, PyObject *a,
+                                            PyObject *b,
+                                            PyObject * const *args,
+                                            Py_ssize_t args_length)
+/*[clinic end generated code: output=70eda18c3667681e input=2b0fcd7bd9bb865c]*/
+{
+    return pack_arguments_2pos_varpos(a, b, args, args_length);
+}
+
 static struct PyMethodDef test_class_methods[] = {
     _TESTCLINIC_TESTCLASS_GET_DEFINING_CLASS_METHODDEF
     _TESTCLINIC_TESTCLASS_GET_DEFINING_CLASS_ARG_METHODDEF
     _TESTCLINIC_TESTCLASS_DEFCLASS_VARPOS_METHODDEF
     _TESTCLINIC_TESTCLASS_DEFCLASS_POSONLY_VARPOS_METHODDEF
+
+    {"varpos_no_fastcall", _PyCFunction_CAST(varpos_no_fastcall),
+        METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""},
+    {"posonly_varpos_no_fastcall", _PyCFunction_CAST(posonly_varpos_no_fastcall),
+        METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""},
+    {"posonly_req_opt_varpos_no_fastcall", _PyCFunction_CAST(posonly_req_opt_varpos_no_fastcall),
+        METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""},
+    {"posonly_poskw_varpos_no_fastcall", _PyCFunction_CAST(posonly_poskw_varpos_no_fastcall),
+        METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""},
+
+    {"varpos_array_no_fastcall",
+        _PyCFunction_CAST(varpos_array_no_fastcall),
+        METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""},
+    {"posonly_varpos_array_no_fastcall",
+        _PyCFunction_CAST(posonly_varpos_array_no_fastcall),
+        METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""},
+    {"posonly_req_opt_varpos_array_no_fastcall",
+        _PyCFunction_CAST(posonly_req_opt_varpos_array_no_fastcall),
+        METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""},
+    {"posonly_poskw_varpos_array_no_fastcall",
+        _PyCFunction_CAST(posonly_poskw_varpos_array_no_fastcall),
+        METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""},
+
     {NULL, NULL}
 };
 
@@ -2023,12 +2286,19 @@ static PyMethodDef tester_methods[] = {
 
     VARPOS_METHODDEF
     POSONLY_VARPOS_METHODDEF
+    POSONLY_REQ_OPT_VARPOS_METHODDEF
     POSONLY_POSKW_VARPOS_METHODDEF
     POSKW_VARPOS_METHODDEF
     POSKW_VARPOS_KWONLY_OPT_METHODDEF
     POSKW_VARPOS_KWONLY_OPT2_METHODDEF
     VARPOS_KWONLY_OPT_METHODDEF
     VARPOS_KWONLY_REQ_OPT_METHODDEF
+
+    VARPOS_ARRAY_METHODDEF
+    POSONLY_VARPOS_ARRAY_METHODDEF
+    POSONLY_REQ_OPT_VARPOS_ARRAY_METHODDEF
+    POSONLY_POSKW_VARPOS_ARRAY_METHODDEF
+
     GH_32092_OOB_METHODDEF
     GH_32092_KW_PASS_METHODDEF
     GH_99233_REFCOUNT_METHODDEF
index 7e29998c7db520945eff929ed80358735030edf0..0f5ae5ec86975384f5a2d1c1d8c98c2aa14ca86e 100644 (file)
@@ -9,6 +9,7 @@ preserve
 #include "pycore_long.h"          // _PyLong_UnsignedShort_Converter()
 #include "pycore_modsupport.h"    // _PyArg_CheckPositional()
 #include "pycore_runtime.h"       // _Py_ID()
+#include "pycore_tuple.h"         // _PyTuple_FromArray()
 
 PyDoc_STRVAR(test_empty_function__doc__,
 "test_empty_function($module, /)\n"
@@ -2530,22 +2531,24 @@ PyDoc_STRVAR(varpos__doc__,
     {"varpos", _PyCFunction_CAST(varpos), METH_FASTCALL, varpos__doc__},
 
 static PyObject *
-varpos_impl(PyObject *module, Py_ssize_t nargs, PyObject *const *args);
+varpos_impl(PyObject *module, PyObject *args);
 
 static PyObject *
 varpos(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
 {
     PyObject *return_value = NULL;
-    Py_ssize_t nvararg = nargs - 0;
-    PyObject *const *__clinic_args = NULL;
+    PyObject *__clinic_args = NULL;
 
-    if (!_PyArg_CheckPositional("varpos", nargs, 0, PY_SSIZE_T_MAX)) {
+    __clinic_args = _PyTuple_FromArray(args, nargs);
+    if (__clinic_args == NULL) {
         goto exit;
     }
-    __clinic_args = args + 0;
-    return_value = varpos_impl(module, nvararg, __clinic_args);
+    return_value = varpos_impl(module, __clinic_args);
 
 exit:
+    /* Cleanup for args */
+    Py_XDECREF(__clinic_args);
+
     return return_value;
 }
 
@@ -2559,26 +2562,75 @@ PyDoc_STRVAR(posonly_varpos__doc__,
 
 static PyObject *
 posonly_varpos_impl(PyObject *module, PyObject *a, PyObject *b,
-                    Py_ssize_t nargs, PyObject *const *args);
+                    PyObject *args);
 
 static PyObject *
 posonly_varpos(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
 {
     PyObject *return_value = NULL;
-    Py_ssize_t nvararg = nargs - 2;
     PyObject *a;
     PyObject *b;
-    PyObject *const *__clinic_args = NULL;
+    PyObject *__clinic_args = NULL;
 
     if (!_PyArg_CheckPositional("posonly_varpos", nargs, 2, PY_SSIZE_T_MAX)) {
         goto exit;
     }
     a = args[0];
     b = args[1];
-    __clinic_args = args + 2;
-    return_value = posonly_varpos_impl(module, a, b, nvararg, __clinic_args);
+    __clinic_args = _PyTuple_FromArray(args + 2, nargs - 2);
+    if (__clinic_args == NULL) {
+        goto exit;
+    }
+    return_value = posonly_varpos_impl(module, a, b, __clinic_args);
 
 exit:
+    /* Cleanup for args */
+    Py_XDECREF(__clinic_args);
+
+    return return_value;
+}
+
+PyDoc_STRVAR(posonly_req_opt_varpos__doc__,
+"posonly_req_opt_varpos($module, a, b=False, /, *args)\n"
+"--\n"
+"\n");
+
+#define POSONLY_REQ_OPT_VARPOS_METHODDEF    \
+    {"posonly_req_opt_varpos", _PyCFunction_CAST(posonly_req_opt_varpos), METH_FASTCALL, posonly_req_opt_varpos__doc__},
+
+static PyObject *
+posonly_req_opt_varpos_impl(PyObject *module, PyObject *a, PyObject *b,
+                            PyObject *args);
+
+static PyObject *
+posonly_req_opt_varpos(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject *a;
+    PyObject *b = Py_False;
+    PyObject *__clinic_args = NULL;
+
+    if (!_PyArg_CheckPositional("posonly_req_opt_varpos", nargs, 1, PY_SSIZE_T_MAX)) {
+        goto exit;
+    }
+    a = args[0];
+    if (nargs < 2) {
+        goto skip_optional;
+    }
+    b = args[1];
+skip_optional:
+    __clinic_args = nargs > 2
+        ? _PyTuple_FromArray(args + 2, nargs - 2)
+        : PyTuple_New(0);
+    if (__clinic_args == NULL) {
+        goto exit;
+    }
+    return_value = posonly_req_opt_varpos_impl(module, a, b, __clinic_args);
+
+exit:
+    /* Cleanup for args */
+    Py_XDECREF(__clinic_args);
+
     return return_value;
 }
 
@@ -2623,22 +2675,30 @@ posonly_poskw_varpos(PyObject *module, PyObject *const *args, Py_ssize_t nargs,
         .kwtuple = KWTUPLE,
     };
     #undef KWTUPLE
-    PyObject *argsbuf[3];
+    PyObject *argsbuf[2];
+    PyObject * const *fastargs;
     PyObject *a;
     PyObject *b;
     PyObject *__clinic_args = NULL;
 
-    args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, 2, argsbuf);
-    if (!args) {
+    fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
+    if (!fastargs) {
+        goto exit;
+    }
+    a = fastargs[0];
+    b = fastargs[1];
+    __clinic_args = nargs > 2
+        ? _PyTuple_FromArray(args + 2, nargs - 2)
+        : PyTuple_New(0);
+    if (__clinic_args == NULL) {
         goto exit;
     }
-    a = args[0];
-    b = args[1];
-    __clinic_args = args[2];
     return_value = posonly_poskw_varpos_impl(module, a, b, __clinic_args);
 
 exit:
+    /* Cleanup for args */
     Py_XDECREF(__clinic_args);
+
     return return_value;
 }
 
@@ -2682,20 +2742,28 @@ poskw_varpos(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
         .kwtuple = KWTUPLE,
     };
     #undef KWTUPLE
-    PyObject *argsbuf[2];
+    PyObject *argsbuf[1];
+    PyObject * const *fastargs;
     PyObject *a;
     PyObject *__clinic_args = NULL;
 
-    args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf);
-    if (!args) {
+    fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+    if (!fastargs) {
+        goto exit;
+    }
+    a = fastargs[0];
+    __clinic_args = nargs > 1
+        ? _PyTuple_FromArray(args + 1, nargs - 1)
+        : PyTuple_New(0);
+    if (__clinic_args == NULL) {
         goto exit;
     }
-    a = args[0];
-    __clinic_args = args[1];
     return_value = poskw_varpos_impl(module, a, __clinic_args);
 
 exit:
+    /* Cleanup for args */
     Py_XDECREF(__clinic_args);
+
     return return_value;
 }
 
@@ -2740,30 +2808,38 @@ poskw_varpos_kwonly_opt(PyObject *module, PyObject *const *args, Py_ssize_t narg
         .kwtuple = KWTUPLE,
     };
     #undef KWTUPLE
-    PyObject *argsbuf[3];
+    PyObject *argsbuf[2];
+    PyObject * const *fastargs;
     Py_ssize_t noptargs = Py_MIN(nargs, 1) + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
     PyObject *a;
     PyObject *__clinic_args = NULL;
     int b = 0;
 
-    args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf);
-    if (!args) {
+    fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+    if (!fastargs) {
         goto exit;
     }
-    a = args[0];
-    __clinic_args = args[1];
+    a = fastargs[0];
     if (!noptargs) {
         goto skip_optional_kwonly;
     }
-    b = PyObject_IsTrue(args[2]);
+    b = PyObject_IsTrue(fastargs[1]);
     if (b < 0) {
         goto exit;
     }
 skip_optional_kwonly:
+    __clinic_args = nargs > 1
+        ? _PyTuple_FromArray(args + 1, nargs - 1)
+        : PyTuple_New(0);
+    if (__clinic_args == NULL) {
+        goto exit;
+    }
     return_value = poskw_varpos_kwonly_opt_impl(module, a, __clinic_args, b);
 
 exit:
+    /* Cleanup for args */
     Py_XDECREF(__clinic_args);
+
     return return_value;
 }
 
@@ -2808,34 +2884,42 @@ poskw_varpos_kwonly_opt2(PyObject *module, PyObject *const *args, Py_ssize_t nar
         .kwtuple = KWTUPLE,
     };
     #undef KWTUPLE
-    PyObject *argsbuf[4];
+    PyObject *argsbuf[3];
+    PyObject * const *fastargs;
     Py_ssize_t noptargs = Py_MIN(nargs, 1) + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
     PyObject *a;
     PyObject *__clinic_args = NULL;
     PyObject *b = Py_False;
     PyObject *c = Py_False;
 
-    args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf);
-    if (!args) {
+    fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+    if (!fastargs) {
         goto exit;
     }
-    a = args[0];
-    __clinic_args = args[1];
+    a = fastargs[0];
     if (!noptargs) {
         goto skip_optional_kwonly;
     }
-    if (args[2]) {
-        b = args[2];
+    if (fastargs[1]) {
+        b = fastargs[1];
         if (!--noptargs) {
             goto skip_optional_kwonly;
         }
     }
-    c = args[3];
+    c = fastargs[2];
 skip_optional_kwonly:
+    __clinic_args = nargs > 1
+        ? _PyTuple_FromArray(args + 1, nargs - 1)
+        : PyTuple_New(0);
+    if (__clinic_args == NULL) {
+        goto exit;
+    }
     return_value = poskw_varpos_kwonly_opt2_impl(module, a, __clinic_args, b, c);
 
 exit:
+    /* Cleanup for args */
     Py_XDECREF(__clinic_args);
+
     return return_value;
 }
 
@@ -2879,25 +2963,31 @@ varpos_kwonly_opt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyO
         .kwtuple = KWTUPLE,
     };
     #undef KWTUPLE
-    PyObject *argsbuf[2];
+    PyObject *argsbuf[1];
+    PyObject * const *fastargs;
     Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
     PyObject *__clinic_args = NULL;
     PyObject *b = Py_False;
 
-    args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, 0, argsbuf);
-    if (!args) {
+    fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf);
+    if (!fastargs) {
         goto exit;
     }
-    __clinic_args = args[0];
     if (!noptargs) {
         goto skip_optional_kwonly;
     }
-    b = args[1];
+    b = fastargs[0];
 skip_optional_kwonly:
+    __clinic_args = _PyTuple_FromArray(args, nargs);
+    if (__clinic_args == NULL) {
+        goto exit;
+    }
     return_value = varpos_kwonly_opt_impl(module, __clinic_args, b);
 
 exit:
+    /* Cleanup for args */
     Py_XDECREF(__clinic_args);
+
     return return_value;
 }
 
@@ -2942,34 +3032,202 @@ varpos_kwonly_req_opt(PyObject *module, PyObject *const *args, Py_ssize_t nargs,
         .kwtuple = KWTUPLE,
     };
     #undef KWTUPLE
-    PyObject *argsbuf[4];
+    PyObject *argsbuf[3];
+    PyObject * const *fastargs;
     Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
     PyObject *__clinic_args = NULL;
     PyObject *a;
     PyObject *b = Py_False;
     PyObject *c = Py_False;
 
-    args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 1, 0, argsbuf);
-    if (!args) {
+    fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 1, argsbuf);
+    if (!fastargs) {
         goto exit;
     }
-    __clinic_args = args[0];
-    a = args[1];
+    a = fastargs[0];
     if (!noptargs) {
         goto skip_optional_kwonly;
     }
-    if (args[2]) {
-        b = args[2];
+    if (fastargs[1]) {
+        b = fastargs[1];
         if (!--noptargs) {
             goto skip_optional_kwonly;
         }
     }
-    c = args[3];
+    c = fastargs[2];
 skip_optional_kwonly:
+    __clinic_args = _PyTuple_FromArray(args, nargs);
+    if (__clinic_args == NULL) {
+        goto exit;
+    }
     return_value = varpos_kwonly_req_opt_impl(module, __clinic_args, a, b, c);
 
 exit:
+    /* Cleanup for args */
     Py_XDECREF(__clinic_args);
+
+    return return_value;
+}
+
+PyDoc_STRVAR(varpos_array__doc__,
+"varpos_array($module, /, *args)\n"
+"--\n"
+"\n");
+
+#define VARPOS_ARRAY_METHODDEF    \
+    {"varpos_array", _PyCFunction_CAST(varpos_array), METH_FASTCALL, varpos_array__doc__},
+
+static PyObject *
+varpos_array_impl(PyObject *module, PyObject * const *args,
+                  Py_ssize_t args_length);
+
+static PyObject *
+varpos_array(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject * const *__clinic_args;
+    Py_ssize_t args_length;
+
+    __clinic_args = args;
+    args_length = nargs;
+    return_value = varpos_array_impl(module, __clinic_args, args_length);
+
+    return return_value;
+}
+
+PyDoc_STRVAR(posonly_varpos_array__doc__,
+"posonly_varpos_array($module, a, b, /, *args)\n"
+"--\n"
+"\n");
+
+#define POSONLY_VARPOS_ARRAY_METHODDEF    \
+    {"posonly_varpos_array", _PyCFunction_CAST(posonly_varpos_array), METH_FASTCALL, posonly_varpos_array__doc__},
+
+static PyObject *
+posonly_varpos_array_impl(PyObject *module, PyObject *a, PyObject *b,
+                          PyObject * const *args, Py_ssize_t args_length);
+
+static PyObject *
+posonly_varpos_array(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject *a;
+    PyObject *b;
+    PyObject * const *__clinic_args;
+    Py_ssize_t args_length;
+
+    if (!_PyArg_CheckPositional("posonly_varpos_array", nargs, 2, PY_SSIZE_T_MAX)) {
+        goto exit;
+    }
+    a = args[0];
+    b = args[1];
+    __clinic_args = args + 2;
+    args_length = nargs - 2;
+    return_value = posonly_varpos_array_impl(module, a, b, __clinic_args, args_length);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(posonly_req_opt_varpos_array__doc__,
+"posonly_req_opt_varpos_array($module, a, b=False, /, *args)\n"
+"--\n"
+"\n");
+
+#define POSONLY_REQ_OPT_VARPOS_ARRAY_METHODDEF    \
+    {"posonly_req_opt_varpos_array", _PyCFunction_CAST(posonly_req_opt_varpos_array), METH_FASTCALL, posonly_req_opt_varpos_array__doc__},
+
+static PyObject *
+posonly_req_opt_varpos_array_impl(PyObject *module, PyObject *a, PyObject *b,
+                                  PyObject * const *args,
+                                  Py_ssize_t args_length);
+
+static PyObject *
+posonly_req_opt_varpos_array(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject *a;
+    PyObject *b = Py_False;
+    PyObject * const *__clinic_args;
+    Py_ssize_t args_length;
+
+    if (!_PyArg_CheckPositional("posonly_req_opt_varpos_array", nargs, 1, PY_SSIZE_T_MAX)) {
+        goto exit;
+    }
+    a = args[0];
+    if (nargs < 2) {
+        goto skip_optional;
+    }
+    b = args[1];
+skip_optional:
+    __clinic_args = nargs > 2 ? args + 2 : args;
+    args_length = Py_MAX(0, nargs - 2);
+    return_value = posonly_req_opt_varpos_array_impl(module, a, b, __clinic_args, args_length);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(posonly_poskw_varpos_array__doc__,
+"posonly_poskw_varpos_array($module, a, /, b, *args)\n"
+"--\n"
+"\n");
+
+#define POSONLY_POSKW_VARPOS_ARRAY_METHODDEF    \
+    {"posonly_poskw_varpos_array", _PyCFunction_CAST(posonly_poskw_varpos_array), METH_FASTCALL|METH_KEYWORDS, posonly_poskw_varpos_array__doc__},
+
+static PyObject *
+posonly_poskw_varpos_array_impl(PyObject *module, PyObject *a, PyObject *b,
+                                PyObject * const *args,
+                                Py_ssize_t args_length);
+
+static PyObject *
+posonly_poskw_varpos_array(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    PyObject *return_value = NULL;
+    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+    #define NUM_KEYWORDS 1
+    static struct {
+        PyGC_Head _this_is_not_used;
+        PyObject_VAR_HEAD
+        PyObject *ob_item[NUM_KEYWORDS];
+    } _kwtuple = {
+        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+        .ob_item = { _Py_LATIN1_CHR('b'), },
+    };
+    #undef NUM_KEYWORDS
+    #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+    #else  // !Py_BUILD_CORE
+    #  define KWTUPLE NULL
+    #endif  // !Py_BUILD_CORE
+
+    static const char * const _keywords[] = {"", "b", NULL};
+    static _PyArg_Parser _parser = {
+        .keywords = _keywords,
+        .fname = "posonly_poskw_varpos_array",
+        .kwtuple = KWTUPLE,
+    };
+    #undef KWTUPLE
+    PyObject *argsbuf[2];
+    PyObject * const *fastargs;
+    PyObject *a;
+    PyObject *b;
+    PyObject * const *__clinic_args;
+    Py_ssize_t args_length;
+
+    fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
+    if (!fastargs) {
+        goto exit;
+    }
+    a = fastargs[0];
+    b = fastargs[1];
+    __clinic_args = nargs > 2 ? args + 2 : args;
+    args_length = Py_MAX(0, nargs - 2);
+    return_value = posonly_poskw_varpos_array_impl(module, a, b, __clinic_args, args_length);
+
+exit:
     return return_value;
 }
 
@@ -3015,7 +3273,8 @@ gh_32092_oob(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
         .kwtuple = KWTUPLE,
     };
     #undef KWTUPLE
-    PyObject *argsbuf[5];
+    PyObject *argsbuf[4];
+    PyObject * const *fastargs;
     Py_ssize_t noptargs = Py_MIN(nargs, 2) + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2;
     PyObject *pos1;
     PyObject *pos2;
@@ -3023,28 +3282,35 @@ gh_32092_oob(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
     PyObject *kw1 = Py_None;
     PyObject *kw2 = Py_None;
 
-    args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, 2, argsbuf);
-    if (!args) {
+    fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
+    if (!fastargs) {
         goto exit;
     }
-    pos1 = args[0];
-    pos2 = args[1];
-    varargs = args[2];
+    pos1 = fastargs[0];
+    pos2 = fastargs[1];
     if (!noptargs) {
         goto skip_optional_kwonly;
     }
-    if (args[3]) {
-        kw1 = args[3];
+    if (fastargs[2]) {
+        kw1 = fastargs[2];
         if (!--noptargs) {
             goto skip_optional_kwonly;
         }
     }
-    kw2 = args[4];
+    kw2 = fastargs[3];
 skip_optional_kwonly:
+    varargs = nargs > 2
+        ? _PyTuple_FromArray(args + 2, nargs - 2)
+        : PyTuple_New(0);
+    if (varargs == NULL) {
+        goto exit;
+    }
     return_value = gh_32092_oob_impl(module, pos1, pos2, varargs, kw1, kw2);
 
 exit:
+    /* Cleanup for varargs */
     Py_XDECREF(varargs);
+
     return return_value;
 }
 
@@ -3090,27 +3356,35 @@ gh_32092_kw_pass(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb
         .kwtuple = KWTUPLE,
     };
     #undef KWTUPLE
-    PyObject *argsbuf[3];
+    PyObject *argsbuf[2];
+    PyObject * const *fastargs;
     Py_ssize_t noptargs = Py_MIN(nargs, 1) + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
     PyObject *pos;
     PyObject *__clinic_args = NULL;
     PyObject *kw = Py_None;
 
-    args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf);
-    if (!args) {
+    fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+    if (!fastargs) {
         goto exit;
     }
-    pos = args[0];
-    __clinic_args = args[1];
+    pos = fastargs[0];
     if (!noptargs) {
         goto skip_optional_kwonly;
     }
-    kw = args[2];
+    kw = fastargs[1];
 skip_optional_kwonly:
+    __clinic_args = nargs > 1
+        ? _PyTuple_FromArray(args + 1, nargs - 1)
+        : PyTuple_New(0);
+    if (__clinic_args == NULL) {
+        goto exit;
+    }
     return_value = gh_32092_kw_pass_impl(module, pos, __clinic_args, kw);
 
 exit:
+    /* Cleanup for args */
     Py_XDECREF(__clinic_args);
+
     return return_value;
 }
 
@@ -3124,23 +3398,24 @@ PyDoc_STRVAR(gh_99233_refcount__doc__,
     {"gh_99233_refcount", _PyCFunction_CAST(gh_99233_refcount), METH_FASTCALL, gh_99233_refcount__doc__},
 
 static PyObject *
-gh_99233_refcount_impl(PyObject *module, Py_ssize_t nargs,
-                       PyObject *const *args);
+gh_99233_refcount_impl(PyObject *module, PyObject *args);
 
 static PyObject *
 gh_99233_refcount(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
 {
     PyObject *return_value = NULL;
-    Py_ssize_t nvararg = nargs - 0;
-    PyObject *const *__clinic_args = NULL;
+    PyObject *__clinic_args = NULL;
 
-    if (!_PyArg_CheckPositional("gh_99233_refcount", nargs, 0, PY_SSIZE_T_MAX)) {
+    __clinic_args = _PyTuple_FromArray(args, nargs);
+    if (__clinic_args == NULL) {
         goto exit;
     }
-    __clinic_args = args + 0;
-    return_value = gh_99233_refcount_impl(module, nvararg, __clinic_args);
+    return_value = gh_99233_refcount_impl(module, __clinic_args);
 
 exit:
+    /* Cleanup for args */
+    Py_XDECREF(__clinic_args);
+
     return return_value;
 }
 
@@ -3220,30 +3495,38 @@ null_or_tuple_for_varargs(PyObject *module, PyObject *const *args, Py_ssize_t na
         .kwtuple = KWTUPLE,
     };
     #undef KWTUPLE
-    PyObject *argsbuf[3];
+    PyObject *argsbuf[2];
+    PyObject * const *fastargs;
     Py_ssize_t noptargs = Py_MIN(nargs, 1) + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
     PyObject *name;
     PyObject *constraints = NULL;
     int covariant = 0;
 
-    args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf);
-    if (!args) {
+    fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+    if (!fastargs) {
         goto exit;
     }
-    name = args[0];
-    constraints = args[1];
+    name = fastargs[0];
     if (!noptargs) {
         goto skip_optional_kwonly;
     }
-    covariant = PyObject_IsTrue(args[2]);
+    covariant = PyObject_IsTrue(fastargs[1]);
     if (covariant < 0) {
         goto exit;
     }
 skip_optional_kwonly:
+    constraints = nargs > 1
+        ? _PyTuple_FromArray(args + 1, nargs - 1)
+        : PyTuple_New(0);
+    if (constraints == NULL) {
+        goto exit;
+    }
     return_value = null_or_tuple_for_varargs_impl(module, name, constraints, covariant);
 
 exit:
+    /* Cleanup for constraints */
     Py_XDECREF(constraints);
+
     return return_value;
 }
 
@@ -3613,17 +3896,23 @@ _testclinic_TestClass_defclass_varpos(PyObject *self, PyTypeObject *cls, PyObjec
     };
     #undef KWTUPLE
     PyObject *argsbuf[1];
+    PyObject * const *fastargs;
     PyObject *__clinic_args = NULL;
 
-    args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, 0, argsbuf);
-    if (!args) {
+    fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf);
+    if (!fastargs) {
+        goto exit;
+    }
+    __clinic_args = _PyTuple_FromArray(args, nargs);
+    if (__clinic_args == NULL) {
         goto exit;
     }
-    __clinic_args = args[0];
     return_value = _testclinic_TestClass_defclass_varpos_impl(self, cls, __clinic_args);
 
 exit:
+    /* Cleanup for args */
     Py_XDECREF(__clinic_args);
+
     return return_value;
 }
 
@@ -3658,22 +3947,335 @@ _testclinic_TestClass_defclass_posonly_varpos(PyObject *self, PyTypeObject *cls,
         .kwtuple = KWTUPLE,
     };
     #undef KWTUPLE
-    PyObject *argsbuf[3];
+    PyObject *argsbuf[2];
+    PyObject * const *fastargs;
     PyObject *a;
     PyObject *b;
     PyObject *__clinic_args = NULL;
 
-    args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, 2, argsbuf);
-    if (!args) {
+    fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
+    if (!fastargs) {
+        goto exit;
+    }
+    a = fastargs[0];
+    b = fastargs[1];
+    __clinic_args = _PyTuple_FromArray(args + 2, nargs - 2);
+    if (__clinic_args == NULL) {
         goto exit;
     }
-    a = args[0];
-    b = args[1];
-    __clinic_args = args[2];
     return_value = _testclinic_TestClass_defclass_posonly_varpos_impl(self, cls, a, b, __clinic_args);
 
 exit:
+    /* Cleanup for args */
+    Py_XDECREF(__clinic_args);
+
+    return return_value;
+}
+
+static PyObject *
+varpos_no_fastcall_impl(PyTypeObject *type, PyObject *args);
+
+static PyObject *
+varpos_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    PyTypeObject *base_tp = &PyBaseObject_Type;
+    PyObject *__clinic_args = NULL;
+
+    if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
+        !_PyArg_NoKeywords("TestClass", kwargs)) {
+        goto exit;
+    }
+    __clinic_args = Py_NewRef(args);
+    return_value = varpos_no_fastcall_impl(type, __clinic_args);
+
+exit:
+    /* Cleanup for args */
+    Py_XDECREF(__clinic_args);
+
+    return return_value;
+}
+
+static PyObject *
+posonly_varpos_no_fastcall_impl(PyTypeObject *type, PyObject *a, PyObject *b,
+                                PyObject *args);
+
+static PyObject *
+posonly_varpos_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    PyTypeObject *base_tp = &PyBaseObject_Type;
+    PyObject *a;
+    PyObject *b;
+    PyObject *__clinic_args = NULL;
+
+    if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
+        !_PyArg_NoKeywords("TestClass", kwargs)) {
+        goto exit;
+    }
+    if (!_PyArg_CheckPositional("TestClass", PyTuple_GET_SIZE(args), 2, PY_SSIZE_T_MAX)) {
+        goto exit;
+    }
+    a = PyTuple_GET_ITEM(args, 0);
+    b = PyTuple_GET_ITEM(args, 1);
+    __clinic_args = PyTuple_GetSlice(args, 2, PY_SSIZE_T_MAX);
+    if (!__clinic_args) {
+        goto exit;
+    }
+    return_value = posonly_varpos_no_fastcall_impl(type, a, b, __clinic_args);
+
+exit:
+    /* Cleanup for args */
+    Py_XDECREF(__clinic_args);
+
+    return return_value;
+}
+
+static PyObject *
+posonly_req_opt_varpos_no_fastcall_impl(PyTypeObject *type, PyObject *a,
+                                        PyObject *b, PyObject *args);
+
+static PyObject *
+posonly_req_opt_varpos_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    PyTypeObject *base_tp = &PyBaseObject_Type;
+    PyObject *a;
+    PyObject *b = Py_False;
+    PyObject *__clinic_args = NULL;
+
+    if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
+        !_PyArg_NoKeywords("TestClass", kwargs)) {
+        goto exit;
+    }
+    if (!_PyArg_CheckPositional("TestClass", PyTuple_GET_SIZE(args), 1, PY_SSIZE_T_MAX)) {
+        goto exit;
+    }
+    a = PyTuple_GET_ITEM(args, 0);
+    if (PyTuple_GET_SIZE(args) < 2) {
+        goto skip_optional;
+    }
+    b = PyTuple_GET_ITEM(args, 1);
+skip_optional:
+    __clinic_args = PyTuple_GetSlice(args, 2, PY_SSIZE_T_MAX);
+    if (!__clinic_args) {
+        goto exit;
+    }
+    return_value = posonly_req_opt_varpos_no_fastcall_impl(type, a, b, __clinic_args);
+
+exit:
+    /* Cleanup for args */
+    Py_XDECREF(__clinic_args);
+
+    return return_value;
+}
+
+static PyObject *
+posonly_poskw_varpos_no_fastcall_impl(PyTypeObject *type, PyObject *a,
+                                      PyObject *b, PyObject *args);
+
+static PyObject *
+posonly_poskw_varpos_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+    #define NUM_KEYWORDS 1
+    static struct {
+        PyGC_Head _this_is_not_used;
+        PyObject_VAR_HEAD
+        PyObject *ob_item[NUM_KEYWORDS];
+    } _kwtuple = {
+        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+        .ob_item = { _Py_LATIN1_CHR('b'), },
+    };
+    #undef NUM_KEYWORDS
+    #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+    #else  // !Py_BUILD_CORE
+    #  define KWTUPLE NULL
+    #endif  // !Py_BUILD_CORE
+
+    static const char * const _keywords[] = {"", "b", NULL};
+    static _PyArg_Parser _parser = {
+        .keywords = _keywords,
+        .fname = "TestClass",
+        .kwtuple = KWTUPLE,
+    };
+    #undef KWTUPLE
+    PyObject *argsbuf[2];
+    PyObject * const *fastargs;
+    Py_ssize_t nargs = PyTuple_GET_SIZE(args);
+    PyObject *a;
+    PyObject *b;
+    PyObject *__clinic_args = NULL;
+
+    fastargs = _PyArg_UnpackKeywordsWithVararg(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 2, 2, 0, argsbuf);
+    if (!fastargs) {
+        goto exit;
+    }
+    a = fastargs[0];
+    b = fastargs[1];
+    __clinic_args = PyTuple_GetSlice(args, 2, PY_SSIZE_T_MAX);
+    if (!__clinic_args) {
+        goto exit;
+    }
+    return_value = posonly_poskw_varpos_no_fastcall_impl(type, a, b, __clinic_args);
+
+exit:
+    /* Cleanup for args */
     Py_XDECREF(__clinic_args);
+
+    return return_value;
+}
+
+static PyObject *
+varpos_array_no_fastcall_impl(PyTypeObject *type, PyObject * const *args,
+                              Py_ssize_t args_length);
+
+static PyObject *
+varpos_array_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    PyTypeObject *base_tp = &PyBaseObject_Type;
+    PyObject * const *__clinic_args;
+    Py_ssize_t args_length;
+
+    if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
+        !_PyArg_NoKeywords("TestClass", kwargs)) {
+        goto exit;
+    }
+    __clinic_args = _PyTuple_ITEMS(args);
+    args_length = PyTuple_GET_SIZE(args);
+    return_value = varpos_array_no_fastcall_impl(type, __clinic_args, args_length);
+
+exit:
+    return return_value;
+}
+
+static PyObject *
+posonly_varpos_array_no_fastcall_impl(PyTypeObject *type, PyObject *a,
+                                      PyObject *b, PyObject * const *args,
+                                      Py_ssize_t args_length);
+
+static PyObject *
+posonly_varpos_array_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    PyTypeObject *base_tp = &PyBaseObject_Type;
+    PyObject *a;
+    PyObject *b;
+    PyObject * const *__clinic_args;
+    Py_ssize_t args_length;
+
+    if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
+        !_PyArg_NoKeywords("TestClass", kwargs)) {
+        goto exit;
+    }
+    if (!_PyArg_CheckPositional("TestClass", PyTuple_GET_SIZE(args), 2, PY_SSIZE_T_MAX)) {
+        goto exit;
+    }
+    a = PyTuple_GET_ITEM(args, 0);
+    b = PyTuple_GET_ITEM(args, 1);
+    __clinic_args = _PyTuple_ITEMS(args) + 2;
+    args_length = PyTuple_GET_SIZE(args) - 2;
+    return_value = posonly_varpos_array_no_fastcall_impl(type, a, b, __clinic_args, args_length);
+
+exit:
+    return return_value;
+}
+
+static PyObject *
+posonly_req_opt_varpos_array_no_fastcall_impl(PyTypeObject *type,
+                                              PyObject *a, PyObject *b,
+                                              PyObject * const *args,
+                                              Py_ssize_t args_length);
+
+static PyObject *
+posonly_req_opt_varpos_array_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    PyTypeObject *base_tp = &PyBaseObject_Type;
+    PyObject *a;
+    PyObject *b = Py_False;
+    PyObject * const *__clinic_args;
+    Py_ssize_t args_length;
+
+    if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
+        !_PyArg_NoKeywords("TestClass", kwargs)) {
+        goto exit;
+    }
+    if (!_PyArg_CheckPositional("TestClass", PyTuple_GET_SIZE(args), 1, PY_SSIZE_T_MAX)) {
+        goto exit;
+    }
+    a = PyTuple_GET_ITEM(args, 0);
+    if (PyTuple_GET_SIZE(args) < 2) {
+        goto skip_optional;
+    }
+    b = PyTuple_GET_ITEM(args, 1);
+skip_optional:
+    __clinic_args = PyTuple_GET_SIZE(args) > 2 ? _PyTuple_ITEMS(args) + 2 : _PyTuple_ITEMS(args);
+    args_length = Py_MAX(0, PyTuple_GET_SIZE(args) - 2);
+    return_value = posonly_req_opt_varpos_array_no_fastcall_impl(type, a, b, __clinic_args, args_length);
+
+exit:
+    return return_value;
+}
+
+static PyObject *
+posonly_poskw_varpos_array_no_fastcall_impl(PyTypeObject *type, PyObject *a,
+                                            PyObject *b,
+                                            PyObject * const *args,
+                                            Py_ssize_t args_length);
+
+static PyObject *
+posonly_poskw_varpos_array_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+    #define NUM_KEYWORDS 1
+    static struct {
+        PyGC_Head _this_is_not_used;
+        PyObject_VAR_HEAD
+        PyObject *ob_item[NUM_KEYWORDS];
+    } _kwtuple = {
+        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+        .ob_item = { _Py_LATIN1_CHR('b'), },
+    };
+    #undef NUM_KEYWORDS
+    #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+    #else  // !Py_BUILD_CORE
+    #  define KWTUPLE NULL
+    #endif  // !Py_BUILD_CORE
+
+    static const char * const _keywords[] = {"", "b", NULL};
+    static _PyArg_Parser _parser = {
+        .keywords = _keywords,
+        .fname = "TestClass",
+        .kwtuple = KWTUPLE,
+    };
+    #undef KWTUPLE
+    PyObject *argsbuf[2];
+    PyObject * const *fastargs;
+    Py_ssize_t nargs = PyTuple_GET_SIZE(args);
+    PyObject *a;
+    PyObject *b;
+    PyObject * const *__clinic_args;
+    Py_ssize_t args_length;
+
+    fastargs = _PyArg_UnpackKeywordsWithVararg(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 2, 2, 0, argsbuf);
+    if (!fastargs) {
+        goto exit;
+    }
+    a = fastargs[0];
+    b = fastargs[1];
+    __clinic_args = PyTuple_GET_SIZE(args) > 2 ? _PyTuple_ITEMS(args) + 2 : _PyTuple_ITEMS(args);
+    args_length = Py_MAX(0, PyTuple_GET_SIZE(args) - 2);
+    return_value = posonly_poskw_varpos_array_no_fastcall_impl(type, a, b, __clinic_args, args_length);
+
+exit:
     return return_value;
 }
-/*[clinic end generated code: output=7662d07e7d29cbeb input=a9049054013a1b77]*/
+/*[clinic end generated code: output=ed3408af146a746c input=a9049054013a1b77]*/
index 95a2cc4cb5ed6d57e1d622b519107045d1396f2b..0e374f100d623946ae9a88050819c724002ab308 100644 (file)
@@ -9,6 +9,7 @@ preserve
 #include "pycore_long.h"          // _PyLong_UnsignedShort_Converter()
 #include "pycore_modsupport.h"    // _PyArg_CheckPositional()
 #include "pycore_runtime.h"       // _Py_ID()
+#include "pycore_tuple.h"         // _PyTuple_FromArray()
 
 PyDoc_STRVAR(depr_star_new__doc__,
 "DeprStarNew(a=None)\n"
@@ -2393,4 +2394,4 @@ depr_multi(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=ca6da2c7137554be input=a9049054013a1b77]*/
+/*[clinic end generated code: output=5dda27c80df7351e input=a9049054013a1b77]*/
index be3bd35b4ffd44402f5110f03fd426fa3e46232c..34b2a79275c279da2211d926eb789256109b0aae 100644 (file)
@@ -8,6 +8,7 @@ preserve
 #endif
 #include "pycore_abstract.h"      // _Py_convert_optional_to_ssize_t()
 #include "pycore_modsupport.h"    // _PyArg_UnpackKeywords()
+#include "pycore_tuple.h"         // _PyTuple_FromArray()
 
 PyDoc_STRVAR(gc_enable__doc__,
 "enable($module, /)\n"
@@ -312,23 +313,24 @@ PyDoc_STRVAR(gc_get_referrers__doc__,
     {"get_referrers", _PyCFunction_CAST(gc_get_referrers), METH_FASTCALL, gc_get_referrers__doc__},
 
 static PyObject *
-gc_get_referrers_impl(PyObject *module, Py_ssize_t nargs,
-                      PyObject *const *args);
+gc_get_referrers_impl(PyObject *module, PyObject *objs);
 
 static PyObject *
 gc_get_referrers(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
 {
     PyObject *return_value = NULL;
-    Py_ssize_t nvararg = nargs - 0;
-    PyObject *const *__clinic_args = NULL;
+    PyObject *objs = NULL;
 
-    if (!_PyArg_CheckPositional("get_referrers", nargs, 0, PY_SSIZE_T_MAX)) {
+    objs = _PyTuple_FromArray(args, nargs);
+    if (objs == NULL) {
         goto exit;
     }
-    __clinic_args = args + 0;
-    return_value = gc_get_referrers_impl(module, nvararg, __clinic_args);
+    return_value = gc_get_referrers_impl(module, objs);
 
 exit:
+    /* Cleanup for objs */
+    Py_XDECREF(objs);
+
     return return_value;
 }
 
@@ -342,23 +344,24 @@ PyDoc_STRVAR(gc_get_referents__doc__,
     {"get_referents", _PyCFunction_CAST(gc_get_referents), METH_FASTCALL, gc_get_referents__doc__},
 
 static PyObject *
-gc_get_referents_impl(PyObject *module, Py_ssize_t nargs,
-                      PyObject *const *args);
+gc_get_referents_impl(PyObject *module, PyObject *objs);
 
 static PyObject *
 gc_get_referents(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
 {
     PyObject *return_value = NULL;
-    Py_ssize_t nvararg = nargs - 0;
-    PyObject *const *__clinic_args = NULL;
+    PyObject *objs = NULL;
 
-    if (!_PyArg_CheckPositional("get_referents", nargs, 0, PY_SSIZE_T_MAX)) {
+    objs = _PyTuple_FromArray(args, nargs);
+    if (objs == NULL) {
         goto exit;
     }
-    __clinic_args = args + 0;
-    return_value = gc_get_referents_impl(module, nvararg, __clinic_args);
+    return_value = gc_get_referents_impl(module, objs);
 
 exit:
+    /* Cleanup for objs */
+    Py_XDECREF(objs);
+
     return return_value;
 }
 
@@ -575,4 +578,4 @@ gc_get_freeze_count(PyObject *module, PyObject *Py_UNUSED(ignored))
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=f488a0d4d6bd3687 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=4f35875870da17c9 input=a9049054013a1b77]*/
index e4bda8a3e62aba4a195cf6587342602a1051fd0c..461f77183cd45b9cf27a4876d4da88724b5135ab 100644 (file)
@@ -18,22 +18,20 @@ PyDoc_STRVAR(math_gcd__doc__,
     {"gcd", _PyCFunction_CAST(math_gcd), METH_FASTCALL, math_gcd__doc__},
 
 static PyObject *
-math_gcd_impl(PyObject *module, Py_ssize_t nargs, PyObject *const *args);
+math_gcd_impl(PyObject *module, PyObject * const *args,
+              Py_ssize_t args_length);
 
 static PyObject *
 math_gcd(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
 {
     PyObject *return_value = NULL;
-    Py_ssize_t nvararg = nargs - 0;
-    PyObject *const *__clinic_args = NULL;
+    PyObject * const *__clinic_args;
+    Py_ssize_t args_length;
 
-    if (!_PyArg_CheckPositional("gcd", nargs, 0, PY_SSIZE_T_MAX)) {
-        goto exit;
-    }
-    __clinic_args = args + 0;
-    return_value = math_gcd_impl(module, nvararg, __clinic_args);
+    __clinic_args = args;
+    args_length = nargs;
+    return_value = math_gcd_impl(module, __clinic_args, args_length);
 
-exit:
     return return_value;
 }
 
@@ -47,22 +45,20 @@ PyDoc_STRVAR(math_lcm__doc__,
     {"lcm", _PyCFunction_CAST(math_lcm), METH_FASTCALL, math_lcm__doc__},
 
 static PyObject *
-math_lcm_impl(PyObject *module, Py_ssize_t nargs, PyObject *const *args);
+math_lcm_impl(PyObject *module, PyObject * const *args,
+              Py_ssize_t args_length);
 
 static PyObject *
 math_lcm(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
 {
     PyObject *return_value = NULL;
-    Py_ssize_t nvararg = nargs - 0;
-    PyObject *const *__clinic_args = NULL;
+    PyObject * const *__clinic_args;
+    Py_ssize_t args_length;
 
-    if (!_PyArg_CheckPositional("lcm", nargs, 0, PY_SSIZE_T_MAX)) {
-        goto exit;
-    }
-    __clinic_args = args + 0;
-    return_value = math_lcm_impl(module, nvararg, __clinic_args);
+    __clinic_args = args;
+    args_length = nargs;
+    return_value = math_lcm_impl(module, __clinic_args, args_length);
 
-exit:
     return return_value;
 }
 
@@ -430,22 +426,20 @@ PyDoc_STRVAR(math_hypot__doc__,
     {"hypot", _PyCFunction_CAST(math_hypot), METH_FASTCALL, math_hypot__doc__},
 
 static PyObject *
-math_hypot_impl(PyObject *module, Py_ssize_t nargs, PyObject *const *args);
+math_hypot_impl(PyObject *module, PyObject * const *args,
+                Py_ssize_t args_length);
 
 static PyObject *
 math_hypot(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
 {
     PyObject *return_value = NULL;
-    Py_ssize_t nvararg = nargs - 0;
-    PyObject *const *__clinic_args = NULL;
+    PyObject * const *__clinic_args;
+    Py_ssize_t args_length;
 
-    if (!_PyArg_CheckPositional("hypot", nargs, 0, PY_SSIZE_T_MAX)) {
-        goto exit;
-    }
-    __clinic_args = args + 0;
-    return_value = math_hypot_impl(module, nvararg, __clinic_args);
+    __clinic_args = args;
+    args_length = nargs;
+    return_value = math_hypot_impl(module, __clinic_args, args_length);
 
-exit:
     return return_value;
 }
 
@@ -1109,4 +1103,4 @@ math_ulp(PyObject *module, PyObject *arg)
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=ff99a737c18d9210 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=cb506f61bc5ef862 input=a9049054013a1b77]*/
index f5fea5aa4dde08594d003d68a659c893d0cbf02e..ad13496b06deafeaddfa1625a310ecbb79ee67c9 100644 (file)
@@ -216,31 +216,21 @@ gc_get_count_impl(PyObject *module)
 /*[clinic input]
 gc.get_referrers
 
-    *objs as args: object
+    *objs: tuple
 
 Return the list of objects that directly refer to any of 'objs'.
 [clinic start generated code]*/
 
 static PyObject *
-gc_get_referrers_impl(PyObject *module, Py_ssize_t nargs,
-                      PyObject *const *args)
-/*[clinic end generated code: output=1d44a7695ea25c40 input=bae96961b14a0922]*/
+gc_get_referrers_impl(PyObject *module, PyObject *objs)
+/*[clinic end generated code: output=929d6dff26f609b9 input=9102be7ebee69ee3]*/
 {
-    PyObject *varargs = _PyTuple_FromArray(args, nargs);
-
-    if (!varargs) {
-        return NULL;
-    }
-    if (PySys_Audit("gc.get_referrers", "(O)", varargs) < 0) {
-        Py_DECREF(varargs);
+    if (PySys_Audit("gc.get_referrers", "(O)", objs) < 0) {
         return NULL;
     }
 
     PyInterpreterState *interp = _PyInterpreterState_GET();
-    PyObject *result = _PyGC_GetReferrers(interp, varargs);
-
-    Py_DECREF(varargs);
-    return result;
+    return _PyGC_GetReferrers(interp, objs);
 }
 
 /* Append obj to list; return true if error (out of memory), false if OK. */
@@ -274,43 +264,34 @@ append_referrents(PyObject *result, PyObject *args)
 /*[clinic input]
 gc.get_referents
 
-    *objs as args: object
+    *objs: tuple
 
 Return the list of objects that are directly referred to by 'objs'.
 [clinic start generated code]*/
 
 static PyObject *
-gc_get_referents_impl(PyObject *module, Py_ssize_t nargs,
-                      PyObject *const *args)
-/*[clinic end generated code: output=e459f3e8c0d19311 input=b3ceab0c34038cbf]*/
+gc_get_referents_impl(PyObject *module, PyObject *objs)
+/*[clinic end generated code: output=6dfde40cd1588e1d input=55c078a6d0248fe0]*/
 {
-    PyObject *varargs = _PyTuple_FromArray(args, nargs);
-
-    if (!varargs) {
-        return NULL;
-    }
-    if (PySys_Audit("gc.get_referents", "(O)", varargs) < 0) {
-        Py_DECREF(varargs);
+    if (PySys_Audit("gc.get_referents", "(O)", objs) < 0) {
         return NULL;
     }
     PyInterpreterState *interp = _PyInterpreterState_GET();
     PyObject *result = PyList_New(0);
 
     if (result == NULL) {
-        Py_DECREF(varargs);
         return NULL;
     }
 
     // NOTE: stop the world is a no-op in default build
     _PyEval_StopTheWorld(interp);
-    int err = append_referrents(result, varargs);
+    int err = append_referrents(result, objs);
     _PyEval_StartTheWorld(interp);
 
     if (err < 0) {
         Py_CLEAR(result);
     }
 
-    Py_DECREF(varargs);
     return result;
 }
 
index 77f50a2001634b6e2f7a87ad067af543573a7463..29638114dd94a9108053c4cf3c8b629a5ddf3edf 100644 (file)
@@ -722,22 +722,23 @@ m_log10(double x)
 /*[clinic input]
 math.gcd
 
-    *integers as args: object
+    *integers as args: array
 
 Greatest Common Divisor.
 [clinic start generated code]*/
 
 static PyObject *
-math_gcd_impl(PyObject *module, Py_ssize_t nargs, PyObject *const *args)
-/*[clinic end generated code: output=b57687fcf431c1b8 input=94e675b7ceeaf0c9]*/
+math_gcd_impl(PyObject *module, PyObject * const *args,
+              Py_ssize_t args_length)
+/*[clinic end generated code: output=a26c95907374ffb4 input=ded7f0ea3850c05c]*/
 {
     // Fast-path for the common case: gcd(int, int)
-    if (nargs == 2 && PyLong_CheckExact(args[0]) && PyLong_CheckExact(args[1]))
+    if (args_length == 2 && PyLong_CheckExact(args[0]) && PyLong_CheckExact(args[1]))
     {
         return _PyLong_GCD(args[0], args[1]);
     }
 
-    if (nargs == 0) {
+    if (args_length == 0) {
         return PyLong_FromLong(0);
     }
 
@@ -745,13 +746,13 @@ math_gcd_impl(PyObject *module, Py_ssize_t nargs, PyObject *const *args)
     if (res == NULL) {
         return NULL;
     }
-    if (nargs == 1) {
+    if (args_length == 1) {
         Py_SETREF(res, PyNumber_Absolute(res));
         return res;
     }
 
     PyObject *one = _PyLong_GetOne();  // borrowed ref
-    for (Py_ssize_t i = 1; i < nargs; i++) {
+    for (Py_ssize_t i = 1; i < args_length; i++) {
         PyObject *x = _PyNumber_Index(args[i]);
         if (x == NULL) {
             Py_DECREF(res);
@@ -804,32 +805,33 @@ long_lcm(PyObject *a, PyObject *b)
 /*[clinic input]
 math.lcm
 
-    *integers as args: object
+    *integers as args: array
 
 Least Common Multiple.
 [clinic start generated code]*/
 
 static PyObject *
-math_lcm_impl(PyObject *module, Py_ssize_t nargs, PyObject *const *args)
-/*[clinic end generated code: output=f3eff0c25e4d7030 input=e64c33e85f4c47c6]*/
+math_lcm_impl(PyObject *module, PyObject * const *args,
+              Py_ssize_t args_length)
+/*[clinic end generated code: output=c8a59a5c2e55c816 input=3e4f4b7cdf948a98]*/
 {
     PyObject *res, *x;
     Py_ssize_t i;
 
-    if (nargs == 0) {
+    if (args_length == 0) {
         return PyLong_FromLong(1);
     }
     res = PyNumber_Index(args[0]);
     if (res == NULL) {
         return NULL;
     }
-    if (nargs == 1) {
+    if (args_length == 1) {
         Py_SETREF(res, PyNumber_Absolute(res));
         return res;
     }
 
     PyObject *zero = _PyLong_GetZero();  // borrowed ref
-    for (i = 1; i < nargs; i++) {
+    for (i = 1; i < args_length; i++) {
         x = PyNumber_Index(args[i]);
         if (x == NULL) {
             Py_DECREF(res);
@@ -2629,7 +2631,7 @@ math_dist_impl(PyObject *module, PyObject *p, PyObject *q)
 /*[clinic input]
 math.hypot
 
-    *coordinates as args: object
+    *coordinates as args: array
 
 Multidimensional Euclidean distance from the origin to a point.
 
@@ -2646,8 +2648,9 @@ For example, the hypotenuse of a 3/4/5 right triangle is:
 [clinic start generated code]*/
 
 static PyObject *
-math_hypot_impl(PyObject *module, Py_ssize_t nargs, PyObject *const *args)
-/*[clinic end generated code: output=dcb6d4b7a1102ee1 input=5c0061a2d11235ed]*/
+math_hypot_impl(PyObject *module, PyObject * const *args,
+                Py_ssize_t args_length)
+/*[clinic end generated code: output=c9de404e24370068 input=1bceaf7d4fdcd9c2]*/
 {
     Py_ssize_t i;
     PyObject *item;
@@ -2657,13 +2660,13 @@ math_hypot_impl(PyObject *module, Py_ssize_t nargs, PyObject *const *args)
     double coord_on_stack[NUM_STACK_ELEMS];
     double *coordinates = coord_on_stack;
 
-    if (nargs > NUM_STACK_ELEMS) {
-        coordinates = (double *) PyMem_Malloc(nargs * sizeof(double));
+    if (args_length > NUM_STACK_ELEMS) {
+        coordinates = (double *) PyMem_Malloc(args_length * sizeof(double));
         if (coordinates == NULL) {
             return PyErr_NoMemory();
         }
     }
-    for (i = 0; i < nargs; i++) {
+    for (i = 0; i < args_length; i++) {
         item = args[i];
         ASSIGN_DOUBLE(x, item, error_exit);
         x = fabs(x);
@@ -2673,7 +2676,7 @@ math_hypot_impl(PyObject *module, Py_ssize_t nargs, PyObject *const *args)
             max = x;
         }
     }
-    result = vector_norm(nargs, coordinates, max, found_nan);
+    result = vector_norm(args_length, coordinates, max, found_nan);
     if (coordinates != coord_on_stack) {
         PyMem_Free(coordinates);
     }
index d6e381a9975050e80b34bd485463f44e12ff6792..986993b4aa9bda1dc50bbc45dbb5ae1dbb99f142 100644 (file)
@@ -3,7 +3,6 @@ preserve
 [clinic start generated code]*/
 
 #include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
-#include "pycore_modsupport.h"    // _PyArg_CheckPositional()
 
 PyDoc_STRVAR(set_pop__doc__,
 "pop($self, /)\n"
@@ -41,22 +40,20 @@ PyDoc_STRVAR(set_update__doc__,
     {"update", _PyCFunction_CAST(set_update), METH_FASTCALL, set_update__doc__},
 
 static PyObject *
-set_update_impl(PySetObject *so, Py_ssize_t nargs, PyObject *const *args);
+set_update_impl(PySetObject *so, PyObject * const *others,
+                Py_ssize_t others_length);
 
 static PyObject *
 set_update(PySetObject *so, PyObject *const *args, Py_ssize_t nargs)
 {
     PyObject *return_value = NULL;
-    Py_ssize_t nvararg = nargs - 0;
-    PyObject *const *__clinic_args = NULL;
+    PyObject * const *others;
+    Py_ssize_t others_length;
 
-    if (!_PyArg_CheckPositional("update", nargs, 0, PY_SSIZE_T_MAX)) {
-        goto exit;
-    }
-    __clinic_args = args + 0;
-    return_value = set_update_impl(so, nvararg, __clinic_args);
+    others = args;
+    others_length = nargs;
+    return_value = set_update_impl(so, others, others_length);
 
-exit:
     return return_value;
 }
 
@@ -142,22 +139,20 @@ PyDoc_STRVAR(set_union__doc__,
     {"union", _PyCFunction_CAST(set_union), METH_FASTCALL, set_union__doc__},
 
 static PyObject *
-set_union_impl(PySetObject *so, Py_ssize_t nargs, PyObject *const *args);
+set_union_impl(PySetObject *so, PyObject * const *others,
+               Py_ssize_t others_length);
 
 static PyObject *
 set_union(PySetObject *so, PyObject *const *args, Py_ssize_t nargs)
 {
     PyObject *return_value = NULL;
-    Py_ssize_t nvararg = nargs - 0;
-    PyObject *const *__clinic_args = NULL;
+    PyObject * const *others;
+    Py_ssize_t others_length;
 
-    if (!_PyArg_CheckPositional("union", nargs, 0, PY_SSIZE_T_MAX)) {
-        goto exit;
-    }
-    __clinic_args = args + 0;
-    return_value = set_union_impl(so, nvararg, __clinic_args);
+    others = args;
+    others_length = nargs;
+    return_value = set_union_impl(so, others, others_length);
 
-exit:
     return return_value;
 }
 
@@ -171,23 +166,20 @@ PyDoc_STRVAR(set_intersection_multi__doc__,
     {"intersection", _PyCFunction_CAST(set_intersection_multi), METH_FASTCALL, set_intersection_multi__doc__},
 
 static PyObject *
-set_intersection_multi_impl(PySetObject *so, Py_ssize_t nargs,
-                            PyObject *const *args);
+set_intersection_multi_impl(PySetObject *so, PyObject * const *others,
+                            Py_ssize_t others_length);
 
 static PyObject *
 set_intersection_multi(PySetObject *so, PyObject *const *args, Py_ssize_t nargs)
 {
     PyObject *return_value = NULL;
-    Py_ssize_t nvararg = nargs - 0;
-    PyObject *const *__clinic_args = NULL;
+    PyObject * const *others;
+    Py_ssize_t others_length;
 
-    if (!_PyArg_CheckPositional("intersection", nargs, 0, PY_SSIZE_T_MAX)) {
-        goto exit;
-    }
-    __clinic_args = args + 0;
-    return_value = set_intersection_multi_impl(so, nvararg, __clinic_args);
+    others = args;
+    others_length = nargs;
+    return_value = set_intersection_multi_impl(so, others, others_length);
 
-exit:
     return return_value;
 }
 
@@ -201,23 +193,20 @@ PyDoc_STRVAR(set_intersection_update_multi__doc__,
     {"intersection_update", _PyCFunction_CAST(set_intersection_update_multi), METH_FASTCALL, set_intersection_update_multi__doc__},
 
 static PyObject *
-set_intersection_update_multi_impl(PySetObject *so, Py_ssize_t nargs,
-                                   PyObject *const *args);
+set_intersection_update_multi_impl(PySetObject *so, PyObject * const *others,
+                                   Py_ssize_t others_length);
 
 static PyObject *
 set_intersection_update_multi(PySetObject *so, PyObject *const *args, Py_ssize_t nargs)
 {
     PyObject *return_value = NULL;
-    Py_ssize_t nvararg = nargs - 0;
-    PyObject *const *__clinic_args = NULL;
+    PyObject * const *others;
+    Py_ssize_t others_length;
 
-    if (!_PyArg_CheckPositional("intersection_update", nargs, 0, PY_SSIZE_T_MAX)) {
-        goto exit;
-    }
-    __clinic_args = args + 0;
-    return_value = set_intersection_update_multi_impl(so, nvararg, __clinic_args);
+    others = args;
+    others_length = nargs;
+    return_value = set_intersection_update_multi_impl(so, others, others_length);
 
-exit:
     return return_value;
 }
 
@@ -255,23 +244,20 @@ PyDoc_STRVAR(set_difference_update__doc__,
     {"difference_update", _PyCFunction_CAST(set_difference_update), METH_FASTCALL, set_difference_update__doc__},
 
 static PyObject *
-set_difference_update_impl(PySetObject *so, Py_ssize_t nargs,
-                           PyObject *const *args);
+set_difference_update_impl(PySetObject *so, PyObject * const *others,
+                           Py_ssize_t others_length);
 
 static PyObject *
 set_difference_update(PySetObject *so, PyObject *const *args, Py_ssize_t nargs)
 {
     PyObject *return_value = NULL;
-    Py_ssize_t nvararg = nargs - 0;
-    PyObject *const *__clinic_args = NULL;
+    PyObject * const *others;
+    Py_ssize_t others_length;
 
-    if (!_PyArg_CheckPositional("difference_update", nargs, 0, PY_SSIZE_T_MAX)) {
-        goto exit;
-    }
-    __clinic_args = args + 0;
-    return_value = set_difference_update_impl(so, nvararg, __clinic_args);
+    others = args;
+    others_length = nargs;
+    return_value = set_difference_update_impl(so, others, others_length);
 
-exit:
     return return_value;
 }
 
@@ -285,23 +271,20 @@ PyDoc_STRVAR(set_difference_multi__doc__,
     {"difference", _PyCFunction_CAST(set_difference_multi), METH_FASTCALL, set_difference_multi__doc__},
 
 static PyObject *
-set_difference_multi_impl(PySetObject *so, Py_ssize_t nargs,
-                          PyObject *const *args);
+set_difference_multi_impl(PySetObject *so, PyObject * const *others,
+                          Py_ssize_t others_length);
 
 static PyObject *
 set_difference_multi(PySetObject *so, PyObject *const *args, Py_ssize_t nargs)
 {
     PyObject *return_value = NULL;
-    Py_ssize_t nvararg = nargs - 0;
-    PyObject *const *__clinic_args = NULL;
+    PyObject * const *others;
+    Py_ssize_t others_length;
 
-    if (!_PyArg_CheckPositional("difference", nargs, 0, PY_SSIZE_T_MAX)) {
-        goto exit;
-    }
-    __clinic_args = args + 0;
-    return_value = set_difference_multi_impl(so, nvararg, __clinic_args);
+    others = args;
+    others_length = nargs;
+    return_value = set_difference_multi_impl(so, others, others_length);
 
-exit:
     return return_value;
 }
 
@@ -536,4 +519,4 @@ set___sizeof__(PySetObject *so, PyObject *Py_UNUSED(ignored))
 
     return return_value;
 }
-/*[clinic end generated code: output=9d4b41191b2c602f input=a9049054013a1b77]*/
+/*[clinic end generated code: output=4b65e7709927f31f input=a9049054013a1b77]*/
index 0ba4ff48bc88044257d860fcb79b7bc01a62a078..3f439a78ded24114d71d024c63196a220361f226 100644 (file)
@@ -49,7 +49,7 @@ typevar_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
         .kwtuple = KWTUPLE,
     };
     #undef KWTUPLE
-    PyObject *argsbuf[7];
+    PyObject *argsbuf[6];
     PyObject * const *fastargs;
     Py_ssize_t nargs = PyTuple_GET_SIZE(args);
     Py_ssize_t noptargs = Py_MIN(nargs, 1) + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 1;
@@ -61,7 +61,7 @@ typevar_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
     int contravariant = 0;
     int infer_variance = 0;
 
-    fastargs = _PyArg_UnpackKeywordsWithVararg(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, 1, argsbuf);
+    fastargs = _PyArg_UnpackKeywordsWithVararg(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, argsbuf);
     if (!fastargs) {
         goto exit;
     }
@@ -70,24 +70,23 @@ typevar_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
         goto exit;
     }
     name = fastargs[0];
-    constraints = fastargs[1];
     if (!noptargs) {
         goto skip_optional_kwonly;
     }
-    if (fastargs[2]) {
-        bound = fastargs[2];
+    if (fastargs[1]) {
+        bound = fastargs[1];
         if (!--noptargs) {
             goto skip_optional_kwonly;
         }
     }
-    if (fastargs[3]) {
-        default_value = fastargs[3];
+    if (fastargs[2]) {
+        default_value = fastargs[2];
         if (!--noptargs) {
             goto skip_optional_kwonly;
         }
     }
-    if (fastargs[4]) {
-        covariant = PyObject_IsTrue(fastargs[4]);
+    if (fastargs[3]) {
+        covariant = PyObject_IsTrue(fastargs[3]);
         if (covariant < 0) {
             goto exit;
         }
@@ -95,8 +94,8 @@ typevar_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
             goto skip_optional_kwonly;
         }
     }
-    if (fastargs[5]) {
-        contravariant = PyObject_IsTrue(fastargs[5]);
+    if (fastargs[4]) {
+        contravariant = PyObject_IsTrue(fastargs[4]);
         if (contravariant < 0) {
             goto exit;
         }
@@ -104,15 +103,21 @@ typevar_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
             goto skip_optional_kwonly;
         }
     }
-    infer_variance = PyObject_IsTrue(fastargs[6]);
+    infer_variance = PyObject_IsTrue(fastargs[5]);
     if (infer_variance < 0) {
         goto exit;
     }
 skip_optional_kwonly:
+    constraints = PyTuple_GetSlice(args, 1, PY_SSIZE_T_MAX);
+    if (!constraints) {
+        goto exit;
+    }
     return_value = typevar_new_impl(type, name, constraints, bound, default_value, covariant, contravariant, infer_variance);
 
 exit:
+    /* Cleanup for constraints */
     Py_XDECREF(constraints);
+
     return return_value;
 }
 
@@ -695,4 +700,4 @@ skip_optional_kwonly:
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=73b39e550e4e336c input=a9049054013a1b77]*/
+/*[clinic end generated code: output=32b9e6ced80d3fb0 input=a9049054013a1b77]*/
index 66d7fc730c555cc50642a28c8ab8cea472a62dfb..2671792190d7a764de6317bbfbc6adac72f56bd9 100644 (file)
@@ -1054,19 +1054,20 @@ set_update_internal(PySetObject *so, PyObject *other)
 /*[clinic input]
 set.update
     so: setobject
-    *others as args: object
+    *others: array
 
 Update the set, adding elements from all others.
 [clinic start generated code]*/
 
 static PyObject *
-set_update_impl(PySetObject *so, Py_ssize_t nargs, PyObject *const *args)
-/*[clinic end generated code: output=050e2a21f8d7d16a input=df4fe486e38cd337]*/
+set_update_impl(PySetObject *so, PyObject * const *others,
+                Py_ssize_t others_length)
+/*[clinic end generated code: output=017c781c992d5c23 input=ed5d78885b076636]*/
 {
     Py_ssize_t i;
 
-    for (i = 0; i < nargs; i++) {
-        PyObject *other = args[i];
+    for (i = 0; i < others_length; i++) {
+        PyObject *other = others[i];
         if (set_update_internal(so, other))
             return NULL;
     }
@@ -1283,14 +1284,15 @@ set_clear_impl(PySetObject *so)
 /*[clinic input]
 set.union
     so: setobject
-    *others as args: object
+    *others: array
 
 Return a new set with elements from the set and all others.
 [clinic start generated code]*/
 
 static PyObject *
-set_union_impl(PySetObject *so, Py_ssize_t nargs, PyObject *const *args)
-/*[clinic end generated code: output=f68ec24d5c19d404 input=ddf088706e9577b2]*/
+set_union_impl(PySetObject *so, PyObject * const *others,
+               Py_ssize_t others_length)
+/*[clinic end generated code: output=b1bfa3d74065f27e input=55a2e81db6347a4f]*/
 {
     PySetObject *result;
     PyObject *other;
@@ -1300,8 +1302,8 @@ set_union_impl(PySetObject *so, Py_ssize_t nargs, PyObject *const *args)
     if (result == NULL)
         return NULL;
 
-    for (i = 0; i < nargs; i++) {
-        other = args[i];
+    for (i = 0; i < others_length; i++) {
+        other = others[i];
         if ((PyObject *)so == other)
             continue;
         if (set_update_local(result, other)) {
@@ -1434,25 +1436,25 @@ set_intersection(PySetObject *so, PyObject *other)
 /*[clinic input]
 set.intersection as set_intersection_multi
     so: setobject
-    *others as args: object
+    *others: array
 
 Return a new set with elements common to the set and all others.
 [clinic start generated code]*/
 
 static PyObject *
-set_intersection_multi_impl(PySetObject *so, Py_ssize_t nargs,
-                            PyObject *const *args)
-/*[clinic end generated code: output=ef0756ddb5f2dee9 input=0d9f3805ccbba6a4]*/
+set_intersection_multi_impl(PySetObject *so, PyObject * const *others,
+                            Py_ssize_t others_length)
+/*[clinic end generated code: output=db9ff9f875132b6b input=36c7b615694cadae]*/
 {
     Py_ssize_t i;
 
-    if (nargs == 0) {
+    if (others_length == 0) {
         return set_copy(so, NULL);
     }
 
     PyObject *result = Py_NewRef(so);
-    for (i = 0; i < nargs; i++) {
-        PyObject *other = args[i];
+    for (i = 0; i < others_length; i++) {
+        PyObject *other = others[i];
         PyObject *newresult;
         Py_BEGIN_CRITICAL_SECTION2(result, other);
         newresult = set_intersection((PySetObject *)result, other);
@@ -1482,19 +1484,19 @@ set_intersection_update(PySetObject *so, PyObject *other)
 /*[clinic input]
 set.intersection_update as set_intersection_update_multi
     so: setobject
-    *others as args: object
+    *others: array
 
 Update the set, keeping only elements found in it and all others.
 [clinic start generated code]*/
 
 static PyObject *
-set_intersection_update_multi_impl(PySetObject *so, Py_ssize_t nargs,
-                                   PyObject *const *args)
-/*[clinic end generated code: output=808d7ad1935b1dfe input=223c1e086aa669a9]*/
+set_intersection_update_multi_impl(PySetObject *so, PyObject * const *others,
+                                   Py_ssize_t others_length)
+/*[clinic end generated code: output=d768b5584675b48d input=782e422fc370e4fc]*/
 {
     PyObject *tmp;
 
-    tmp = set_intersection_multi_impl(so, nargs, args);
+    tmp = set_intersection_multi_impl(so, others, others_length);
     if (tmp == NULL)
         return NULL;
     Py_BEGIN_CRITICAL_SECTION(so);
@@ -1672,20 +1674,20 @@ set_difference_update_internal(PySetObject *so, PyObject *other)
 /*[clinic input]
 set.difference_update
     so: setobject
-    *others as args: object
+    *others: array
 
 Update the set, removing elements found in others.
 [clinic start generated code]*/
 
 static PyObject *
-set_difference_update_impl(PySetObject *so, Py_ssize_t nargs,
-                           PyObject *const *args)
-/*[clinic end generated code: output=55f850c27748d312 input=024e6baa6fbcbb3d]*/
+set_difference_update_impl(PySetObject *so, PyObject * const *others,
+                           Py_ssize_t others_length)
+/*[clinic end generated code: output=04a22179b322cfe6 input=93ac28ba5b233696]*/
 {
     Py_ssize_t i;
 
-    for (i = 0; i < nargs; i++) {
-        PyObject *other = args[i];
+    for (i = 0; i < others_length; i++) {
+        PyObject *other = others[i];
         int rv;
         Py_BEGIN_CRITICAL_SECTION2(so, other);
         rv = set_difference_update_internal(so, other);
@@ -1790,32 +1792,32 @@ set_difference(PySetObject *so, PyObject *other)
 /*[clinic input]
 set.difference as set_difference_multi
     so: setobject
-    *others as args: object
+    *others: array
 
 Return a new set with elements in the set that are not in the others.
 [clinic start generated code]*/
 
 static PyObject *
-set_difference_multi_impl(PySetObject *so, Py_ssize_t nargs,
-                          PyObject *const *args)
-/*[clinic end generated code: output=8150d008c00523f3 input=ba78ea5f099e58df]*/
+set_difference_multi_impl(PySetObject *so, PyObject * const *others,
+                          Py_ssize_t others_length)
+/*[clinic end generated code: output=b0d33fb05d5477a7 input=c1eb448d483416ad]*/
 {
     Py_ssize_t i;
     PyObject *result, *other;
 
-    if (nargs == 0) {
+    if (others_length == 0) {
         return set_copy(so, NULL);
     }
 
-    other = args[0];
+    other = others[0];
     Py_BEGIN_CRITICAL_SECTION2(so, other);
     result = set_difference(so, other);
     Py_END_CRITICAL_SECTION2();
     if (result == NULL)
         return NULL;
 
-    for (i = 1; i < nargs; i++) {
-        other = args[i];
+    for (i = 1; i < others_length; i++) {
+        other = others[i];
         int rv;
         Py_BEGIN_CRITICAL_SECTION(other);
         rv = set_difference_update_internal((PySetObject *)result, other);
index f75a8d4ac0ccd4b4b14e895ba5e971a215efce8a..b47279686cc2ed2023d7a125019b15520eb4e2ce 100644 (file)
@@ -7,6 +7,7 @@ preserve
 #  include "pycore_runtime.h"     // _Py_ID()
 #endif
 #include "pycore_modsupport.h"    // _PyArg_UnpackKeywords()
+#include "pycore_tuple.h"         // _PyTuple_FromArray()
 
 PyDoc_STRVAR(builtin___import____doc__,
 "__import__($module, /, name, globals=None, locals=None, fromlist=(),\n"
@@ -933,7 +934,8 @@ builtin_print(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec
         .kwtuple = KWTUPLE,
     };
     #undef KWTUPLE
-    PyObject *argsbuf[5];
+    PyObject *argsbuf[4];
+    PyObject * const *fastargs;
     Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
     PyObject *__clinic_args = NULL;
     PyObject *sep = Py_None;
@@ -941,41 +943,46 @@ builtin_print(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec
     PyObject *file = Py_None;
     int flush = 0;
 
-    args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, 0, argsbuf);
-    if (!args) {
+    fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf);
+    if (!fastargs) {
         goto exit;
     }
-    __clinic_args = args[0];
     if (!noptargs) {
         goto skip_optional_kwonly;
     }
-    if (args[1]) {
-        sep = args[1];
+    if (fastargs[0]) {
+        sep = fastargs[0];
         if (!--noptargs) {
             goto skip_optional_kwonly;
         }
     }
-    if (args[2]) {
-        end = args[2];
+    if (fastargs[1]) {
+        end = fastargs[1];
         if (!--noptargs) {
             goto skip_optional_kwonly;
         }
     }
-    if (args[3]) {
-        file = args[3];
+    if (fastargs[2]) {
+        file = fastargs[2];
         if (!--noptargs) {
             goto skip_optional_kwonly;
         }
     }
-    flush = PyObject_IsTrue(args[4]);
+    flush = PyObject_IsTrue(fastargs[3]);
     if (flush < 0) {
         goto exit;
     }
 skip_optional_kwonly:
+    __clinic_args = _PyTuple_FromArray(args, nargs);
+    if (__clinic_args == NULL) {
+        goto exit;
+    }
     return_value = builtin_print_impl(module, __clinic_args, sep, end, file, flush);
 
 exit:
+    /* Cleanup for args */
     Py_XDECREF(__clinic_args);
+
     return return_value;
 }
 
@@ -1228,4 +1235,4 @@ builtin_issubclass(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=435d3f286a863c49 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=76b27cf4164f257e input=a9049054013a1b77]*/
index a764343ea9ee3f40abd2f85fe239412442c091fd..d529994ad3ac0d157ac55f508a33e2e0e22345a9 100644 (file)
@@ -2308,13 +2308,11 @@ vgetargskeywordsfast(PyObject *args, PyObject *keywords,
 }
 
 
-#undef _PyArg_UnpackKeywords
-
 PyObject * const *
-_PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs,
+_PyArg_UnpackKeywordsEx(PyObject *const *args, Py_ssize_t nargs,
                       PyObject *kwargs, PyObject *kwnames,
                       struct _PyArg_Parser *parser,
-                      int minpos, int maxpos, int minkw,
+                      int minpos, int maxpos, int minkw, int varpos,
                       PyObject **buf)
 {
     PyObject *kwtuple;
@@ -2360,11 +2358,11 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs,
     else {
         nkwargs = 0;
     }
-    if (nkwargs == 0 && minkw == 0 && minpos <= nargs && nargs <= maxpos) {
+    if (nkwargs == 0 && minkw == 0 && minpos <= nargs && (varpos || nargs <= maxpos)) {
         /* Fast path. */
         return args;
     }
-    if (nargs + nkwargs > maxargs) {
+    if (!varpos && nargs + nkwargs > maxargs) {
         /* Adding "keyword" (when nargs == 0) prevents producing wrong error
            messages in some special cases (see bpo-31229). */
         PyErr_Format(PyExc_TypeError,
@@ -2377,7 +2375,7 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs,
                      nargs + nkwargs);
         return NULL;
     }
-    if (nargs > maxpos) {
+    if (!varpos && nargs > maxpos) {
         if (maxpos == 0) {
             PyErr_Format(PyExc_TypeError,
                          "%.200s%s takes no positional arguments",
@@ -2402,13 +2400,16 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs,
                      " (%zd given)",
                      (parser->fname == NULL) ? "function" : parser->fname,
                      (parser->fname == NULL) ? "" : "()",
-                     minposonly < maxpos ? "at least" : "exactly",
+                     (varpos || minposonly < maxpos) ? "at least" : "exactly",
                      minposonly,
                      minposonly == 1 ? "" : "s",
                      nargs);
         return NULL;
     }
 
+    if (varpos) {
+        nargs = Py_MIN(maxpos, nargs);
+    }
     /* copy tuple args */
     for (i = 0; i < nargs; i++) {
         buf[i] = args[i];
@@ -2486,157 +2487,6 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs,
     return buf;
 }
 
-PyObject * const *
-_PyArg_UnpackKeywordsWithVararg(PyObject *const *args, Py_ssize_t nargs,
-                                PyObject *kwargs, PyObject *kwnames,
-                                struct _PyArg_Parser *parser,
-                                int minpos, int maxpos, int minkw,
-                                int vararg, PyObject **buf)
-{
-    PyObject *kwtuple;
-    PyObject *keyword;
-    Py_ssize_t varargssize = 0;
-    int i, posonly, minposonly, maxargs;
-    int reqlimit = minkw ? maxpos + minkw : minpos;
-    Py_ssize_t nkwargs;
-    PyObject * const *kwstack = NULL;
-
-    assert(kwargs == NULL || PyDict_Check(kwargs));
-    assert(kwargs == NULL || kwnames == NULL);
-
-    if (parser == NULL) {
-        PyErr_BadInternalCall();
-        return NULL;
-    }
-
-    if (kwnames != NULL && !PyTuple_Check(kwnames)) {
-        PyErr_BadInternalCall();
-        return NULL;
-    }
-
-    if (args == NULL && nargs == 0) {
-        args = buf;
-    }
-
-    if (parser_init(parser) < 0) {
-        return NULL;
-    }
-
-    kwtuple = parser->kwtuple;
-    posonly = parser->pos;
-    minposonly = Py_MIN(posonly, minpos);
-    maxargs = posonly + (int)PyTuple_GET_SIZE(kwtuple);
-    if (kwargs != NULL) {
-        nkwargs = PyDict_GET_SIZE(kwargs);
-    }
-    else if (kwnames != NULL) {
-        nkwargs = PyTuple_GET_SIZE(kwnames);
-        kwstack = args + nargs;
-    }
-    else {
-        nkwargs = 0;
-    }
-    if (nargs < minposonly) {
-        PyErr_Format(PyExc_TypeError,
-                     "%.200s%s takes %s %d positional argument%s"
-                     " (%zd given)",
-                     (parser->fname == NULL) ? "function" : parser->fname,
-                     (parser->fname == NULL) ? "" : "()",
-                     minposonly < maxpos ? "at least" : "exactly",
-                     minposonly,
-                     minposonly == 1 ? "" : "s",
-                     nargs);
-        return NULL;
-    }
-
-    /* create varargs tuple */
-    varargssize = nargs - maxpos;
-    if (varargssize < 0) {
-        varargssize = 0;
-    }
-    buf[vararg] = PyTuple_New(varargssize);
-    if (!buf[vararg]) {
-        return NULL;
-    }
-
-    /* copy tuple args */
-    for (i = 0; i < nargs; i++) {
-        if (i >= vararg) {
-            PyTuple_SET_ITEM(buf[vararg], i - vararg, Py_NewRef(args[i]));
-            continue;
-        }
-        else {
-            buf[i] = args[i];
-        }
-    }
-
-    /* copy keyword args using kwtuple to drive process */
-    for (i = Py_MAX((int)nargs, posonly) - Py_SAFE_DOWNCAST(varargssize, Py_ssize_t, int); i < maxargs; i++) {
-        PyObject *current_arg;
-        if (nkwargs) {
-            keyword = PyTuple_GET_ITEM(kwtuple, i - posonly);
-            if (kwargs != NULL) {
-                if (PyDict_GetItemRef(kwargs, keyword, &current_arg) < 0) {
-                    goto exit;
-                }
-            }
-            else {
-                current_arg = find_keyword(kwnames, kwstack, keyword);
-            }
-        }
-        else {
-            current_arg = NULL;
-        }
-
-        /* If an arguments is passed in as a keyword argument,
-         * it should be placed before `buf[vararg]`.
-         *
-         * For example:
-         * def f(a, /, b, *args):
-         *     pass
-         * f(1, b=2)
-         *
-         * This `buf` array should be: [1, 2, NULL].
-         * In this case, nargs < vararg.
-         *
-         * Otherwise, we leave a place at `buf[vararg]` for vararg tuple
-         * so the index is `i + 1`. */
-        if (i < vararg) {
-            buf[i] = current_arg;
-        }
-        else {
-            buf[i + 1] = current_arg;
-        }
-
-        if (current_arg) {
-            Py_DECREF(current_arg);
-            --nkwargs;
-        }
-        else if (i < minpos || (maxpos <= i && i < reqlimit)) {
-            /* Less arguments than required */
-            keyword = PyTuple_GET_ITEM(kwtuple, i - posonly);
-            PyErr_Format(PyExc_TypeError,  "%.200s%s missing required "
-                         "argument '%U' (pos %d)",
-                         (parser->fname == NULL) ? "function" : parser->fname,
-                         (parser->fname == NULL) ? "" : "()",
-                         keyword, i+1);
-            goto exit;
-        }
-    }
-
-    if (nkwargs > 0) {
-        error_unexpected_keyword_arg(kwargs, kwnames, kwtuple, parser->fname);
-        goto exit;
-    }
-
-    return buf;
-
-exit:
-    Py_XDECREF(buf[vararg]);
-    return NULL;
-}
-
-
 static const char *
 skipitem(const char **p_format, va_list *p_va, int flags)
 {
index 4227e938d7f8da02a216c1401e3afa25c9d20094..ff4f303c4a2bec477301a151a34b4b70e6fc0b5b 100644 (file)
@@ -164,7 +164,7 @@ def _parse(srclines, anon_name, **srckwargs):
 # We use defaults that cover most files.  Files with bigger declarations
 # are covered elsewhere (MAX_SIZES in cpython/_parser.py).
 
-def _iter_source(lines, *, maxtext=10_000, maxlines=200, showtext=False):
+def _iter_source(lines, *, maxtext=11_000, maxlines=200, showtext=False):
     maxtext = maxtext if maxtext and maxtext > 0 else None
     maxlines = maxlines if maxlines and maxlines > 0 else None
     filestack = []
index 32aba81ab8a850e0e4e56252311c83418d3abcf7..32d2c045b06bca6f4e822281334683b2efa1c55d 100644 (file)
@@ -15,7 +15,7 @@ from libclinic.function import (
     Module, Class, Function, Parameter,
     permute_optional_groups,
     GETTER, SETTER, METHOD_INIT)
-from libclinic.converters import defining_class_converter, self_converter
+from libclinic.converters import self_converter
 from libclinic.parse_args import ParseArgsCodeGen
 if TYPE_CHECKING:
     from libclinic.app import Clinic
@@ -396,12 +396,6 @@ class CLanguage(Language):
         first_optional = len(selfless)
         positional = selfless and selfless[-1].is_positional_only()
         has_option_groups = False
-        requires_defining_class = (len(selfless)
-                                   and isinstance(selfless[0].converter,
-                                                  defining_class_converter))
-        pass_vararg_directly = (all(p.is_positional_only() or p.is_vararg()
-                                    for p in selfless)
-                                and not requires_defining_class)
 
         # offset i by -1 because first_optional needs to ignore self
         for i, p in enumerate(parameters, -1):
@@ -410,9 +404,6 @@ class CLanguage(Language):
             if (i != -1) and (p.default is not unspecified):
                 first_optional = min(first_optional, i)
 
-            if p.is_vararg() and not pass_vararg_directly:
-                data.cleanup.append(f"Py_XDECREF({c.parser_name});")
-
             # insert group variable
             group = p.group
             if last_group != group:
@@ -424,11 +415,6 @@ class CLanguage(Language):
                     data.impl_parameters.append("int " + group_name)
                     has_option_groups = True
 
-            if p.is_vararg() and pass_vararg_directly:
-                data.impl_arguments.append('nvararg')
-                data.impl_parameters.append('Py_ssize_t nargs')
-                p.converter.type = 'PyObject *const *'
-
             c.render(p, data)
 
         if has_option_groups and (not positional):
index 86853bb4fba25327b6783bc7e84cb5a696f09d57..2c93dda35410308344456873e66e45e2ce228f9e 100644 (file)
@@ -312,7 +312,7 @@ class CConverter(metaclass=CConverterAutoRegister):
     def length_name(self) -> str:
         """Computes the name of the associated "length" variable."""
         assert self.length is not None
-        return self.parser_name + "_length"
+        return self.name + "_length"
 
     # Why is this one broken out separately?
     # For "positional-only" function parsing,
index bd5c2a2b73b94a9e228471091755ac801cad213f..2d103c941cbf239cd16ecec61a0754f5fd898314 100644 (file)
@@ -1228,3 +1228,30 @@ class self_converter(CConverter):
             type_object = cls.type_object
             type_ptr = f'PyTypeObject *base_tp = {type_object};'
             template_dict['base_type_ptr'] = type_ptr
+
+
+# Converters for var-positional parameter.
+
+class varpos_tuple_converter(CConverter):
+    type = 'PyObject *'
+    format_unit = ''
+    c_default = 'NULL'
+
+    def cleanup(self) -> str:
+        return f"""Py_XDECREF({self.parser_name});\n"""
+
+    def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None:
+        raise AssertionError('should never be called')
+
+class varpos_array_converter(CConverter):
+    type = 'PyObject * const *'
+    format_unit = ''
+    length = True
+    c_ignored_default = ''
+
+    def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None:
+        raise AssertionError('should never be called')
+
+# XXX: temporary
+class varpos_object_converter(varpos_tuple_converter):
+    pass
index 5ca3bd5cb6c3f115cdde6092b763c262c9cf5dc0..4b4a8b9969d14251d84bcaf912c7a47077ef4736 100644 (file)
@@ -925,16 +925,17 @@ class DSLParser:
 
         parameter_name = parameter.arg
         name, legacy, kwargs = self.parse_converter(parameter.annotation)
+        if is_vararg:
+            name = 'varpos_' + name
 
         value: object
         if not default:
-            if self.parameter_state is ParamState.OPTIONAL:
-                fail(f"Can't have a parameter without a default ({parameter_name!r}) "
-                      "after a parameter with a default!")
             if is_vararg:
                 value = NULL
-                kwargs.setdefault('c_default', "NULL")
             else:
+                if self.parameter_state is ParamState.OPTIONAL:
+                    fail(f"Can't have a parameter without a default ({parameter_name!r}) "
+                          "after a parameter with a default!")
                 value = unspecified
             if 'py_default' in kwargs:
                 fail("You can't specify py_default without specifying a default value!")
index 559d4fbdd09c579952d2c354cab2c117aaff9724..2ce4e7512148d26eaf03530c2f0e79f7847d18d7 100644 (file)
@@ -217,8 +217,7 @@ class ParseArgsCodeGen:
     min_pos: int = 0
     max_pos: int = 0
     min_kw_only: int = 0
-    pseudo_args: int = 0
-    vararg: int | str = NO_VARARG
+    varpos: Parameter | None = None
 
     docstring_prototype: str
     docstring_definition: str
@@ -246,6 +245,13 @@ class ParseArgsCodeGen:
         if self.parameters and isinstance(self.parameters[0].converter, defining_class_converter):
             self.requires_defining_class = True
             del self.parameters[0]
+
+        for i, p in enumerate(self.parameters):
+            if p.is_vararg():
+                self.varpos = p
+                del self.parameters[i]
+                break
+
         self.converters = [p.converter for p in self.parameters]
 
         if self.func.critical_section:
@@ -257,18 +263,13 @@ class ParseArgsCodeGen:
         self.min_pos = 0
         self.max_pos = 0
         self.min_kw_only = 0
-        self.pseudo_args = 0
         for i, p in enumerate(self.parameters, 1):
             if p.is_keyword_only():
                 assert not p.is_positional_only()
                 if not p.is_optional():
-                    self.min_kw_only = i - self.max_pos - int(self.vararg != NO_VARARG)
-            elif p.is_vararg():
-                self.pseudo_args += 1
-                self.vararg = i - 1
+                    self.min_kw_only = i - self.max_pos
             else:
-                if self.vararg == NO_VARARG:
-                    self.max_pos = i
+                self.max_pos = i
                 if p.is_positional_only():
                     self.pos_only = i
                 if not p.is_optional():
@@ -285,6 +286,7 @@ class ParseArgsCodeGen:
         return (len(self.parameters) == 1
                 and self.parameters[0].is_positional_only()
                 and not self.converters[0].is_optional()
+                and not self.varpos
                 and not self.requires_defining_class
                 and not self.is_new_or_init())
 
@@ -315,7 +317,8 @@ class ParseArgsCodeGen:
 
     def init_limited_capi(self) -> None:
         self.limited_capi = self.codegen.limited_capi
-        if self.limited_capi and (self.pseudo_args or
+        if self.limited_capi and (
+                (self.varpos and self.pos_only < len(self.parameters)) or
                 (any(p.is_optional() for p in self.parameters) and
                  any(p.is_keyword_only() and not p.is_optional() for p in self.parameters)) or
                 any(c.broken_limited_capi for c in self.converters)):
@@ -447,6 +450,74 @@ class ParseArgsCodeGen:
         parser_code = '    {option_group_parsing}'
         self.parser_body(parser_code)
 
+    def _parse_vararg(self) -> str:
+        assert self.varpos is not None
+        paramname = self.varpos.converter.parser_name
+        if self.varpos.converter.length:
+            if not self.fastcall:
+                self.codegen.add_include('pycore_tuple.h',
+                                        '_PyTuple_ITEMS()')
+            start = 'args' if self.fastcall else '_PyTuple_ITEMS(args)'
+            size = 'nargs' if self.fastcall else 'PyTuple_GET_SIZE(args)'
+            if self.max_pos:
+                if min(self.pos_only, self.min_pos) < self.max_pos:
+                    start = f'{size} > {self.max_pos} ? {start} + {self.max_pos} : {start}'
+                    size = f'Py_MAX(0, {size} - {self.max_pos})'
+                else:
+                    start = f'{start} + {self.max_pos}'
+                    size = f'{size} - {self.max_pos}'
+            return f"""
+                {paramname} = {start};
+                {self.varpos.converter.length_name} = {size};
+                """
+
+        if self.fastcall:
+            if self.limited_capi:
+                if min(self.pos_only, self.min_pos) < self.max_pos:
+                    size = f'Py_MAX(nargs - {self.max_pos}, 0)'
+                else:
+                    size = f'nargs - {self.max_pos}' if self.max_pos else 'nargs'
+                return f"""
+                    {paramname} = PyTuple_New({size});
+                    if (!{paramname}) {{{{
+                        goto exit;
+                    }}}}
+                    for (Py_ssize_t i = {self.max_pos}; i < nargs; ++i) {{{{
+                        PyTuple_SET_ITEM({paramname}, i - {self.max_pos}, Py_NewRef(args[i]));
+                    }}}}
+                    """
+            else:
+                self.codegen.add_include('pycore_tuple.h',
+                                         '_PyTuple_FromArray()')
+                if min(self.pos_only, self.min_pos) < self.max_pos:
+                    return f"""
+                        {paramname} = nargs > {self.max_pos}
+                            ? _PyTuple_FromArray(args + {self.max_pos}, nargs - {self.max_pos})
+                            : PyTuple_New(0);
+                        if ({paramname} == NULL) {{{{
+                            goto exit;
+                        }}}}
+                        """
+                else:
+                    start = f'args + {self.max_pos}' if self.max_pos else 'args'
+                    size = f'nargs - {self.max_pos}' if self.max_pos else 'nargs'
+                    return f"""
+                        {paramname} = _PyTuple_FromArray({start}, {size});
+                        if ({paramname} == NULL) {{{{
+                            goto exit;
+                        }}}}
+                        """
+        else:
+            if self.max_pos:
+                return f"""
+                    {paramname} = PyTuple_GetSlice(args, {self.max_pos}, PY_SSIZE_T_MAX);
+                    if (!{paramname}) {{{{
+                        goto exit;
+                    }}}}
+                    """
+            else:
+                return f"{paramname} = Py_NewRef(args);\n"
+
     def parse_pos_only(self) -> None:
         if self.fastcall:
             # positional-only, but no option groups
@@ -469,14 +540,9 @@ class ParseArgsCodeGen:
                 nargs = 'PyTuple_GET_SIZE(args)'
                 argname_fmt = 'PyTuple_GET_ITEM(args, %d)'
 
-        if self.vararg != NO_VARARG:
-            self.declarations = f"Py_ssize_t nvararg = {nargs} - {self.max_pos};"
-        else:
-            self.declarations = ""
-
-        max_args = NO_VARARG if (self.vararg != NO_VARARG) else self.max_pos
+        parser_code = []
+        max_args = NO_VARARG if self.varpos else self.max_pos
         if self.limited_capi:
-            parser_code = []
             if nargs != 'nargs':
                 nargs_def = f'Py_ssize_t nargs = {nargs};'
                 parser_code.append(libclinic.normalize_snippet(nargs_def, indent=4))
@@ -509,33 +575,27 @@ class ParseArgsCodeGen:
                         }}}}
                         """,
                     indent=4))
-        else:
+        elif self.min_pos or max_args != NO_VARARG:
             self.codegen.add_include('pycore_modsupport.h',
                                      '_PyArg_CheckPositional()')
-            parser_code = [libclinic.normalize_snippet(f"""
+            parser_code.append(libclinic.normalize_snippet(f"""
                 if (!_PyArg_CheckPositional("{{name}}", {nargs}, {self.min_pos}, {max_args})) {{{{
                     goto exit;
                 }}}}
-                """, indent=4)]
+                """, indent=4))
 
         has_optional = False
         use_parser_code = True
         for i, p in enumerate(self.parameters):
-            if p.is_vararg():
-                var = p.converter.parser_name
-                if self.fastcall:
-                    code = f"{var} = args + {self.vararg};"
-                else:
-                    code = f"{var} = _PyTuple_CAST(args)->ob_item;"
-                formatted_code = libclinic.normalize_snippet(code, indent=4)
-                parser_code.append(formatted_code)
-                continue
-
             displayname = p.get_displayname(i+1)
             argname = argname_fmt % i
             parsearg: str | None
             parsearg = p.converter.parse_arg(argname, displayname, limited_capi=self.limited_capi)
             if parsearg is None:
+                if self.varpos:
+                    raise ValueError(
+                        f"Using converter {p.converter} is not supported "
+                        f"in function with var-positional parameter")
                 use_parser_code = False
                 parser_code = []
                 break
@@ -551,6 +611,8 @@ class ParseArgsCodeGen:
         if use_parser_code:
             if has_optional:
                 parser_code.append("skip_optional:")
+            if self.varpos:
+                parser_code.append(libclinic.normalize_snippet(self._parse_vararg(), indent=4))
         else:
             for parameter in self.parameters:
                 parameter.converter.use_converter()
@@ -575,7 +637,7 @@ class ParseArgsCodeGen:
                         goto exit;
                     }}
                     """, indent=4)]
-        self.parser_body(*parser_code, declarations=self.declarations)
+        self.parser_body(*parser_code)
 
     def parse_general(self, clang: CLanguage) -> None:
         parsearg: str | None
@@ -589,7 +651,7 @@ class ParseArgsCodeGen:
 
         has_optional_kw = (
             max(self.pos_only, self.min_pos) + self.min_kw_only
-            < len(self.converters) - int(self.vararg != NO_VARARG)
+            < len(self.converters)
         )
 
         use_parser_code = True
@@ -598,57 +660,53 @@ class ParseArgsCodeGen:
             use_parser_code = False
             self.fastcall = False
         else:
-            if self.vararg == NO_VARARG:
+            if not self.varpos:
                 self.codegen.add_include('pycore_modsupport.h',
                                          '_PyArg_UnpackKeywords()')
-                args_declaration = "_PyArg_UnpackKeywords", "%s, %s, %s" % (
-                    self.min_pos,
-                    self.max_pos,
-                    self.min_kw_only
-                )
+                unpack_func = '_PyArg_UnpackKeywords'
                 nargs = "nargs"
             else:
                 self.codegen.add_include('pycore_modsupport.h',
                                          '_PyArg_UnpackKeywordsWithVararg()')
-                args_declaration = "_PyArg_UnpackKeywordsWithVararg", "%s, %s, %s, %s" % (
-                    self.min_pos,
-                    self.max_pos,
-                    self.min_kw_only,
-                    self.vararg
-                )
+                unpack_func = '_PyArg_UnpackKeywordsWithVararg'
                 nargs = f"Py_MIN(nargs, {self.max_pos})" if self.max_pos else "0"
 
             if self.fastcall:
                 self.flags = "METH_FASTCALL|METH_KEYWORDS"
                 self.parser_prototype = PARSER_PROTOTYPE_FASTCALL_KEYWORDS
-                argname_fmt = 'args[%d]'
                 self.declarations = declare_parser(self.func, codegen=self.codegen)
-                self.declarations += "\nPyObject *argsbuf[%s];" % len(self.converters)
+                self.declarations += "\nPyObject *argsbuf[%s];" % (len(self.converters) or 1)
+                if self.varpos:
+                    self.declarations += "\nPyObject * const *fastargs;"
+                    argsname = 'fastargs'
+                    argname_fmt = 'fastargs[%d]'
+                else:
+                    argsname = 'args'
+                    argname_fmt = 'args[%d]'
                 if has_optional_kw:
                     self.declarations += "\nPy_ssize_t noptargs = %s + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - %d;" % (nargs, self.min_pos + self.min_kw_only)
-                parser_code = [libclinic.normalize_snippet("""
-                    args = %s(args, nargs, NULL, kwnames, &_parser, %s, argsbuf);
-                    if (!args) {{
-                        goto exit;
-                    }}
-                    """ % args_declaration, indent=4)]
+                unpack_args = 'args, nargs, NULL, kwnames'
             else:
                 # positional-or-keyword arguments
                 self.flags = "METH_VARARGS|METH_KEYWORDS"
                 self.parser_prototype = PARSER_PROTOTYPE_KEYWORD
+                argsname = 'fastargs'
                 argname_fmt = 'fastargs[%d]'
                 self.declarations = declare_parser(self.func, codegen=self.codegen)
-                self.declarations += "\nPyObject *argsbuf[%s];" % len(self.converters)
+                self.declarations += "\nPyObject *argsbuf[%s];" % (len(self.converters) or 1)
                 self.declarations += "\nPyObject * const *fastargs;"
                 self.declarations += "\nPy_ssize_t nargs = PyTuple_GET_SIZE(args);"
                 if has_optional_kw:
                     self.declarations += "\nPy_ssize_t noptargs = %s + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - %d;" % (nargs, self.min_pos + self.min_kw_only)
-                parser_code = [libclinic.normalize_snippet("""
-                    fastargs = %s(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, %s, argsbuf);
-                    if (!fastargs) {{
-                        goto exit;
-                    }}
-                    """ % args_declaration, indent=4)]
+                unpack_args = '_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL'
+            unpack_args += (f', &_parser, {self.min_pos}, {self.max_pos}, '
+                            f'{self.min_kw_only}, argsbuf')
+            parser_code = [libclinic.normalize_snippet(f"""
+                {argsname} = {unpack_func}({unpack_args});
+                if (!{argsname}) {{{{
+                    goto exit;
+                }}}}
+                """, indent=4)]
 
         if self.requires_defining_class:
             self.flags = 'METH_METHOD|' + self.flags
@@ -697,8 +755,6 @@ class ParseArgsCodeGen:
                     else:
                         label = 'skip_optional_kwonly'
                         first_opt = self.max_pos + self.min_kw_only
-                        if self.vararg != NO_VARARG:
-                            first_opt += 1
                     if i == first_opt:
                         add_label = label
                         parser_code.append(libclinic.normalize_snippet("""
@@ -724,6 +780,8 @@ class ParseArgsCodeGen:
         if use_parser_code:
             if add_label:
                 parser_code.append("%s:" % add_label)
+            if self.varpos:
+                parser_code.append(libclinic.normalize_snippet(self._parse_vararg(), indent=4))
         else:
             for parameter in self.parameters:
                 parameter.converter.use_converter()
@@ -914,14 +972,14 @@ class ParseArgsCodeGen:
         # previous call to parser_body. this is used for an awful hack.
         self.parser_body_fields: tuple[str, ...] = ()
 
-        if not self.parameters:
+        if not self.parameters and not self.varpos:
             self.parse_no_args()
         elif self.use_meth_o():
             self.parse_one_arg()
         elif self.has_option_groups():
             self.parse_option_groups()
         elif (not self.requires_defining_class
-              and self.pos_only == len(self.parameters) - self.pseudo_args):
+              and self.pos_only == len(self.parameters)):
             self.parse_pos_only()
         else:
             self.parse_general(clang)