about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJosh Stone <jistone@redhat.com>2021-10-01 12:29:09 -0700
committerJosh Stone <jistone@redhat.com>2021-10-01 12:29:09 -0700
commitd6fde80cb4a769af72a5e50c8742c676627f24df (patch)
tree8ea5881f0c0f6c3a4bcd3322913fb4fdf70a5b4f
parented937594d3912ced11f6f35a90bb8bf591909d2a (diff)
downloadrust-d6fde80cb4a769af72a5e50c8742c676627f24df.tar.gz
rust-d6fde80cb4a769af72a5e50c8742c676627f24df.zip
Include the length in BTree hashes
This change makes it consistent with `Hash` for all other collections.
-rw-r--r--library/alloc/src/collections/btree/map.rs1
-rw-r--r--library/alloc/tests/btree_set_hash.rs14
2 files changed, 13 insertions, 2 deletions
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index 3b7c92818f6..0039aeb49e9 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -1968,6 +1968,7 @@ impl<'a, K: Ord + Copy, V: Copy> Extend<(&'a K, &'a V)> for BTreeMap<K, V> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K: Hash, V: Hash> Hash for BTreeMap<K, V> {
     fn hash<H: Hasher>(&self, state: &mut H) {
+        self.len().hash(state);
         for elt in self {
             elt.hash(state);
         }
diff --git a/library/alloc/tests/btree_set_hash.rs b/library/alloc/tests/btree_set_hash.rs
index e06a95ded94..ab275ac4353 100644
--- a/library/alloc/tests/btree_set_hash.rs
+++ b/library/alloc/tests/btree_set_hash.rs
@@ -1,9 +1,8 @@
+use crate::hash;
 use std::collections::BTreeSet;
 
 #[test]
 fn test_hash() {
-    use crate::hash;
-
     let mut x = BTreeSet::new();
     let mut y = BTreeSet::new();
 
@@ -17,3 +16,14 @@ fn test_hash() {
 
     assert_eq!(hash(&x), hash(&y));
 }
+
+#[test]
+fn test_prefix_free() {
+    let x = BTreeSet::from([1, 2, 3]);
+    let y = BTreeSet::<i32>::new();
+
+    // If hashed by iteration alone, `(x, y)` and `(y, x)` would visit the same
+    // order of elements, resulting in the same hash. But now that we also hash
+    // the length, they get distinct sequences of hashed data.
+    assert_ne!(hash(&(&x, &y)), hash(&(&y, &x)));
+}