diff --git a/changelog.d/503.change.rst b/changelog.d/503.change.rst new file mode 100644 index 00000000..3b064fec --- /dev/null +++ b/changelog.d/503.change.rst @@ -0,0 +1 @@ +Clarified documentation for hashing to warn that hashable objects should be deeply immutable (in their usage, even if this is not enforced). diff --git a/docs/hashing.rst b/docs/hashing.rst index b0a61c34..4d31107a 100644 --- a/docs/hashing.rst +++ b/docs/hashing.rst @@ -66,7 +66,9 @@ For a more thorough explanation of this topic, please refer to this blog post: ` Hashing and Mutability ---------------------- Changing any field involved in hash code computation after the first call to `__hash__` (typically this would be after its insertion into a hash-based collection) can result in silent bugs. -Therefore, it is strongly recommended that hashable classes be ``frozen``. +Therefore, it is strongly recommended that hashable classes be ``frozen.`` +Beware, however, that this is not a complete guarantee of safety: +if a field points to an object and that object is mutated, the hash code may change, but ``frozen`` will not protect you. Hash Code Caching diff --git a/src/attr/_make.py b/src/attr/_make.py index 1373536a..843c76bd 100644 --- a/src/attr/_make.py +++ b/src/attr/_make.py @@ -843,10 +843,10 @@ def attrs( :param bool cache_hash: Ensure that the object's hash code is computed only once and stored on the object. If this is set to ``True``, hashing must be either explicitly or implicitly enabled for this - class. If the hash code is cached, then no attributes of this - class which participate in hash code computation may be mutated - after object creation. - + class. If the hash code is cached, avoid any reassignments of + fields involved in hash code computation or mutations of the objects + those fields point to after object creation. If such changes occur, + the behavior of the object's hash code is undefined. .. versionadded:: 16.0.0 *slots* .. versionadded:: 16.1.0 *frozen*