Issue #16602: When a weakref's target was part of a long deallocation chain, the object could remain reachable through its weakref even though its refcount had dropped to zero.

Thanks to Eugene Toder for diagnosing and reporting the issue.
diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py
index b7c72bd..3d86cb7 100644
--- a/Lib/test/test_weakref.py
+++ b/Lib/test/test_weakref.py
@@ -774,6 +774,27 @@
         self.assertEqual(hash(a), hash(42))
         self.assertRaises(TypeError, hash, b)
 
+    def test_trashcan_16602(self):
+        # Issue #16602: when a weakref's target was part of a long
+        # deallocation chain, the trashcan mechanism could delay clearing
+        # of the weakref and make the target object visible from outside
+        # code even though its refcount had dropped to 0.  A crash ensued.
+        class C(object):
+            def __init__(self, parent):
+                if not parent:
+                    return
+                wself = weakref.ref(self)
+                def cb(wparent):
+                    o = wself()
+                self.wparent = weakref.ref(parent, cb)
+
+        d = weakref.WeakKeyDictionary()
+        root = c = C(None)
+        for n in range(100):
+            d[c] = c = C(c)
+        del root
+        gc.collect()
+
 
 class SubclassableWeakrefTestCase(TestBase):