From ab3f7bad99edffcab88d0c3876bcdf5bac07acc3 Mon Sep 17 00:00:00 2001 From: An Long Date: Wed, 5 Aug 2026 01:10:41 +0900 Subject: [PATCH] gh-155181: Untrack frozensets created from set literals when possible --- Lib/test/test_set.py | 11 +++++++++++ .../2026-08-05-01-10-20.gh-issue-155181.jj8jhk.rst | 3 +++ Objects/setobject.c | 1 + 3 files changed, 15 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-08-05-01-10-20.gh-issue-155181.jj8jhk.rst diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py index 9bfd4bc7d636699..54d229b71def9a7 100644 --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -762,6 +762,17 @@ def test_constructor_identity(self): t = self.thetype(s) self.assertEqual(id(s), id(t)) + def test_gc_tracking(self): + # gh-140232: frozensets whose elements can never be tracked by the + # GC are not tracked, including the compiled frozenset({...}) form + s = {1, 2} + self.assertFalse(gc.is_tracked(frozenset(s))) + self.assertFalse(gc.is_tracked(frozenset({1, 2}))) + self.assertFalse(gc.is_tracked(frozenset({x for x in range(2)}))) + class C: + pass + self.assertTrue(gc.is_tracked(frozenset({C()}))) + def test_hash(self): self.assertEqual(hash(self.thetype('abcdeb')), hash(self.thetype('ebecda'))) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-08-05-01-10-20.gh-issue-155181.jj8jhk.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-08-05-01-10-20.gh-issue-155181.jj8jhk.rst new file mode 100644 index 000000000000000..1acf8fda95e4652 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-08-05-01-10-20.gh-issue-155181.jj8jhk.rst @@ -0,0 +1,3 @@ +:class:`frozenset` objects created from a set literal or a set comprehension +are now untracked by the garbage collector when none of their elements can +be tracked. diff --git a/Objects/setobject.c b/Objects/setobject.c index 8fdd1eb26118c0a..2b7fce6be3c1bd2 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -1574,6 +1574,7 @@ _PySet_Freeze(PyObject *set) assert(PySet_CheckExact(set)); assert(_PyObject_IsUniquelyReferenced(set)); set->ob_type = &PyFrozenSet_Type; + _PyFrozenSet_MaybeUntrack(set); return Py_NewRef(set); }