changeset: 95592:a60b7945ef87 user: Antoine Pitrou date: Mon Apr 13 20:10:06 2015 +0200 files: Lib/test/test_descr.py Lib/test/test_gc.py Misc/NEWS Objects/typeobject.c description: Issue #23726: Don't enable GC for user subclasses of non-GC types that don't add any new fields. Patch by Eugene Toder. diff -r 3583e5191b96 -r a60b7945ef87 Lib/test/test_descr.py --- a/Lib/test/test_descr.py Mon Apr 13 20:02:33 2015 +0200 +++ b/Lib/test/test_descr.py Mon Apr 13 20:10:06 2015 +0200 @@ -3020,8 +3020,6 @@ cant(object(), list) cant(list(), object) class Int(int): __slots__ = [] - cant(2, Int) - cant(Int(), int) cant(True, int) cant(2, bool) o = object() diff -r 3583e5191b96 -r a60b7945ef87 Lib/test/test_gc.py --- a/Lib/test/test_gc.py Mon Apr 13 20:02:33 2015 +0200 +++ b/Lib/test/test_gc.py Mon Apr 13 20:10:06 2015 +0200 @@ -546,11 +546,31 @@ class UserClass: pass + + class UserInt(int): + pass + + # Base class is object; no extra fields. + class UserClassSlots: + __slots__ = () + + # Base class is fixed size larger than object; no extra fields. + class UserFloatSlots(float): + __slots__ = () + + # Base class is variable size; no extra fields. + class UserIntSlots(int): + __slots__ = () + self.assertTrue(gc.is_tracked(gc)) self.assertTrue(gc.is_tracked(UserClass)) self.assertTrue(gc.is_tracked(UserClass())) + self.assertTrue(gc.is_tracked(UserInt())) self.assertTrue(gc.is_tracked([])) self.assertTrue(gc.is_tracked(set())) + self.assertFalse(gc.is_tracked(UserClassSlots())) + self.assertFalse(gc.is_tracked(UserFloatSlots())) + self.assertFalse(gc.is_tracked(UserIntSlots())) def test_bug1055820b(self): # Corresponds to temp2b.py in the bug report. diff -r 3583e5191b96 -r a60b7945ef87 Misc/NEWS --- a/Misc/NEWS Mon Apr 13 20:02:33 2015 +0200 +++ b/Misc/NEWS Mon Apr 13 20:10:06 2015 +0200 @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #23726: Don't enable GC for user subclasses of non-GC types that + don't add any new fields. Patch by Eugene Toder. + - Issue #23309: Avoid a deadlock at shutdown if a daemon thread is aborted while it is holding a lock to a buffered I/O object, and the main thread tries to use the same I/O object (typically stdout or stderr). A fatal diff -r 3583e5191b96 -r a60b7945ef87 Objects/typeobject.c --- a/Objects/typeobject.c Mon Apr 13 20:02:33 2015 +0200 +++ b/Objects/typeobject.c Mon Apr 13 20:10:06 2015 +0200 @@ -2645,9 +2645,10 @@ } type->tp_dealloc = subtype_dealloc; - /* Enable GC unless there are really no instance variables possible */ - if (!(type->tp_basicsize == sizeof(PyObject) && - type->tp_itemsize == 0)) + /* Enable GC unless this class is not adding new instance variables and + the base class did not use GC. */ + if ((base->tp_flags & Py_TPFLAGS_HAVE_GC) || + type->tp_basicsize > base->tp_basicsize) type->tp_flags |= Py_TPFLAGS_HAVE_GC; /* Always override allocation strategy to use regular heap */