From 3743f92c11c23743a4bc0b64b4c61562b4b866a9 Mon Sep 17 00:00:00 2001 From: cocolato Date: Wed, 15 Apr 2026 23:38:15 +0800 Subject: [PATCH 1/2] make sure abc.register update type_version --- Lib/test/test_type_cache.py | 20 ++++++++++++++++++++ Objects/typeobject.c | 14 ++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/Lib/test/test_type_cache.py b/Lib/test/test_type_cache.py index 22ad9f6243eda9..849a2afd8ed798 100644 --- a/Lib/test/test_type_cache.py +++ b/Lib/test/test_type_cache.py @@ -1,4 +1,5 @@ """ Tests for the internal type cache in CPython. """ +import collections.abc import dis import unittest import warnings @@ -114,6 +115,25 @@ class HolderSub(Holder): Holder.set_value() HolderSub.value + def test_abc_register_invalidates_subclass_versions(self): + class Parent: + pass + + class Child(Parent): + pass + + type_assign_version(Parent) + type_assign_version(Child) + parent_version = type_get_version(Parent) + child_version = type_get_version(Child) + if parent_version == 0 or child_version == 0: + self.skipTest("Could not assign valid type versions") + + collections.abc.Mapping.register(Parent) + + self.assertEqual(type_get_version(Parent), 0) + self.assertEqual(type_get_version(Child), 0) + @support.cpython_only class TypeCacheWithSpecializationTests(unittest.TestCase): def tearDown(self): diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 08b95cfbc6ce59..45404b02a4a13f 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -6419,9 +6419,23 @@ set_flags_recursive(PyTypeObject *self, unsigned long mask, unsigned long flags) void _PyType_SetFlagsRecursive(PyTypeObject *self, unsigned long mask, unsigned long flags) { + BEGIN_TYPE_LOCK(); + /* Invalidate the old version before changing flags. This must happen + before types_stop_world(); immutable/static-builtin types are + skipped because set_flags_recursive() does not touch them. */ + if (!PyType_HasFeature(self, Py_TPFLAGS_IMMUTABLETYPE) && + (self->tp_flags & mask) != flags) + { + type_modified_unlocked(self); + } + /* Keep TYPE_LOCK held while waiting for stop-the-world so no thread + can reassign a version tag before the flag update. */ + type_lock_prevent_release(); types_stop_world(); set_flags_recursive(self, mask, flags); types_start_world(); + type_lock_allow_release(); + END_TYPE_LOCK(); } /* This is similar to PyObject_GenericGetAttr(), From 67e25c42e84e1f018aee07558d0230ab71e61001 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 15:48:06 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2026-04-15-15-48-04.gh-issue-148450.2MEVqH.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-15-15-48-04.gh-issue-148450.2MEVqH.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-15-15-48-04.gh-issue-148450.2MEVqH.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-15-15-48-04.gh-issue-148450.2MEVqH.rst new file mode 100644 index 00000000000000..2a7d0d9bb3a7f7 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-15-15-48-04.gh-issue-148450.2MEVqH.rst @@ -0,0 +1 @@ +Fix ``abc.register()`` so it invalidates type version tags for registered classes.