diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py index 9bfd4bc7d63669..54d229b71def9a 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 00000000000000..1acf8fda95e465 --- /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 8fdd1eb26118c0..2b7fce6be3c1bd 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); }