]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-96751: Remove dead code from `CALL_FUNCTION_EX` opcode (GH-96752)
authorNikita Sobolev <mail@sobolevn.me>
Thu, 15 Sep 2022 09:33:13 +0000 (12:33 +0300)
committerGitHub <noreply@github.com>
Thu, 15 Sep 2022 09:33:13 +0000 (10:33 +0100)
Lib/test/test_extcall.py
Misc/NEWS.d/next/Core and Builtins/2022-09-11-12-43-43.gh-issue-96751.anRT6a.rst [new file with mode: 0644]
Python/ceval.c

index 11d39ec63a49e329d18224d1995ecd36057f6128..d9d85fe79af883f30603baf1f1a527244f582f0e 100644 (file)
@@ -382,6 +382,27 @@ Test a kwargs mapping with duplicated keys.
       ...
     TypeError: test.test_extcall.g() got multiple values for keyword argument 'x'
 
+Call with dict subtype:
+
+    >>> class MyDict(dict):
+    ...     pass
+
+    >>> def s1(**kwargs):
+    ...     return kwargs
+    >>> def s2(*args, **kwargs):
+    ...     return (args, kwargs)
+    >>> def s3(*, n, **kwargs):
+    ...     return (n, kwargs)
+
+    >>> md = MyDict({'a': 1, 'b': 2})
+    >>> assert s1(**md) == {'a': 1, 'b': 2}
+    >>> assert s2(*(1, 2), **md) == ((1, 2), {'a': 1, 'b': 2})
+    >>> assert s3(**MyDict({'n': 1, 'b': 2})) == (1, {'b': 2})
+    >>> s3(**md)
+    Traceback (most recent call last):
+      ...
+    TypeError: s3() missing 1 required keyword-only argument: 'n'
+
 Another helper function
 
     >>> def f2(*a, **b):
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-09-11-12-43-43.gh-issue-96751.anRT6a.rst b/Misc/NEWS.d/next/Core and Builtins/2022-09-11-12-43-43.gh-issue-96751.anRT6a.rst
new file mode 100644 (file)
index 0000000..fb5b73e
--- /dev/null
@@ -0,0 +1 @@
+Remove dead code from ``CALL_FUNCTION_EX`` opcode.
index 1cf72461f4cf5770decf49e9897bb4f15504176b..b61cc0852ed96a677f711c1575f266171b7a04d3 100644 (file)
@@ -4716,19 +4716,8 @@ handle_eval_breaker:
             PyObject *func, *callargs, *kwargs = NULL, *result;
             if (oparg & 0x01) {
                 kwargs = POP();
-                if (!PyDict_CheckExact(kwargs)) {
-                    PyObject *d = PyDict_New();
-                    if (d == NULL)
-                        goto error;
-                    if (_PyDict_MergeEx(d, kwargs, 2) < 0) {
-                        Py_DECREF(d);
-                        format_kwargs_error(tstate, SECOND(), kwargs);
-                        Py_DECREF(kwargs);
-                        goto error;
-                    }
-                    Py_DECREF(kwargs);
-                    kwargs = d;
-                }
+                // DICT_MERGE is called before this opcode if there are kwargs.
+                // It converts all dict subtypes in kwargs into regular dicts.
                 assert(PyDict_CheckExact(kwargs));
             }
             callargs = POP();