#1061 (mainly by Thomas Wouters): use weak sets for abc caches.
diff --git a/Lib/weakref.py b/Lib/weakref.py
index c5e5247..c54a072 100644
--- a/Lib/weakref.py
+++ b/Lib/weakref.py
@@ -337,3 +337,108 @@
                 d[ref(key, self._remove)] = value
         if len(kwargs):
             self.update(kwargs)
+
+
+class WeakSet:
+    def __init__(self, data=None):
+        self.data = set()
+        def _remove(item, selfref=ref(self)):
+            self = selfref()
+            if self is not None:
+                self.data.discard(item)
+        self._remove = _remove
+        if data is not None:
+            self.update(data)
+
+    def __iter__(self):
+        for itemref in self.data:
+            item = itemref()
+            if item is not None:
+                yield item
+
+    def __contains__(self, item):
+        return ref(item) in self.data
+
+    def __reduce__(self):
+        return (self.__class__, (list(self),),
+                getattr(self, '__dict__', None))
+
+    def add(self, item):
+        self.data.add(ref(item, self._remove))
+
+    def clear(self):
+        self.data.clear()
+
+    def copy(self):
+        return self.__class__(self)
+
+    def pop(self):
+        while True:
+            itemref = self.data.pop()
+            item = itemref()
+            if item is not None:
+                return item
+
+    def remove(self, item):
+        self.data.remove(ref(item))
+
+    def discard(self, item):
+        self.data.discard(ref(item))
+
+    def update(self, other):
+        if isinstance(other, self.__class__):
+            self.data.update(other.data)
+        else:
+            for element in other:
+                self.add(element)
+    __ior__ = update
+
+    # Helper functions for simple delegating methods.
+    def _apply(self, other, method):
+        if not isinstance(other, self.__class__):
+            other = self.__class__(other)
+        newdata = method(other.data)
+        newset = self.__class__()
+        newset.data = newdata
+        return newset
+
+    def _apply_mutate(self, other, method):
+        if not isinstance(other, self.__class__):
+            other = self.__class__(other)
+        method(other)
+
+    def difference(self, other):
+        return self._apply(other, self.data.difference)
+    __sub__ = difference
+
+    def difference_update(self, other):
+        self._apply_mutate(self, self.data.difference_update)
+    __isub__ = difference_update
+
+    def intersection(self, other):
+        return self._apply(other, self.data.intersection)
+    __and__ = intersection
+
+    def intersection_update(self, other):
+        self._apply_mutate(self, self.data.intersection_update)
+    __iand__ = intersection_update
+
+    def issubset(self, other):
+        return self.data.issubset(ref(item) for item in other)
+    __lt__ = issubset
+
+    def issuperset(self, other):
+        return self.data.issuperset(ref(item) for item in other)
+    __gt__ = issuperset
+
+    def symmetric_difference(self, other):
+        return self._apply(other, self.data.symmetric_difference)
+    __xor__ = symmetric_difference
+
+    def symmetric_difference_update(self, other):
+        self._apply_mutate(other, self.data.symmetric_difference_update)
+    __ixor__ = symmetric_difference_update
+
+    def union(self, other):
+        self._apply_mutate(other, self.data.union)
+    __or__ = union