https://github.com/python/cpython/commit/e66d0399cc2e78fcdb6a0113cd757d2ce567ca7c
commit: e66d0399cc2e78fcdb6a0113cd757d2ce567ca7c
branch: main
author: Mark Shannon <[email protected]>
committer: markshannon <[email protected]>
date: 2024-02-01T19:39:32Z
summary:

GH-114806. Don't specialize calls to classes with metaclasses. (GH-114870)

files:
A Misc/NEWS.d/next/Core and 
Builtins/2024-02-01-18-16-52.gh-issue-114806.wrH2J6.rst
M Lib/test/test_class.py
M Python/specialize.c

diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py
index 1531aad4f1f779..d59271435e9eb0 100644
--- a/Lib/test/test_class.py
+++ b/Lib/test/test_class.py
@@ -771,6 +771,22 @@ def add_one_level():
         with self.assertRaises(RecursionError):
             add_one_level()
 
+    def testMetaclassCallOptimization(self):
+        calls = 0
+
+        class TypeMetaclass(type):
+            def __call__(cls, *args, **kwargs):
+                nonlocal calls
+                calls += 1
+                return type.__call__(cls, *args, **kwargs)
+
+        class Type(metaclass=TypeMetaclass):
+            def __init__(self, obj):
+                self._obj = obj
+
+        for i in range(100):
+            Type(i)
+        self.assertEqual(calls, 100)
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/Misc/NEWS.d/next/Core and 
Builtins/2024-02-01-18-16-52.gh-issue-114806.wrH2J6.rst b/Misc/NEWS.d/next/Core 
and Builtins/2024-02-01-18-16-52.gh-issue-114806.wrH2J6.rst
new file mode 100644
index 00000000000000..795f2529df8207
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and 
Builtins/2024-02-01-18-16-52.gh-issue-114806.wrH2J6.rst 
@@ -0,0 +1,3 @@
+No longer specialize calls to classes, if those classes have metaclasses.
+Fixes bug where the ``__call__`` method of the metaclass was not being
+called.
diff --git a/Python/specialize.c b/Python/specialize.c
index a9efbe0453b94e..e38e3556a6d642 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -540,6 +540,7 @@ _PyCode_Quicken(PyCodeObject *code)
 #define SPEC_FAIL_CALL_METHOD_WRAPPER 28
 #define SPEC_FAIL_CALL_OPERATOR_WRAPPER 29
 #define SPEC_FAIL_CALL_INIT_NOT_SIMPLE 30
+#define SPEC_FAIL_CALL_METACLASS 31
 
 /* COMPARE_OP */
 #define SPEC_FAIL_COMPARE_OP_DIFFERENT_TYPES 12
@@ -1757,6 +1758,10 @@ specialize_class_call(PyObject *callable, _Py_CODEUNIT 
*instr, int nargs)
             SPEC_FAIL_CALL_STR : SPEC_FAIL_CALL_CLASS_NO_VECTORCALL);
         return -1;
     }
+    if (Py_TYPE(tp) != &PyType_Type) {
+        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_METACLASS);
+        return -1;
+    }
     if (tp->tp_new == PyBaseObject_Type.tp_new) {
         PyFunctionObject *init = get_init_for_simple_managed_python_class(tp);
         if (type_get_version(tp, CALL) == 0) {

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to