String
и str
реализуют Hash
, поэтому мы можем получить sh любое из них. Похоже, что как собственные, так и заимствованные строки в настоящее время имеют sh одно и то же значение, поэтому это утверждение выполняется успешно:
use std::hash::Hash;
use std::hash::Hasher;
use std::collections::hash_map::DefaultHasher;
pub fn main() {
let hash1 = {
let x: String = "abc".to_owned();
let mut hasher = DefaultHasher::new();
x.hash(&mut hasher);
hasher.finish()
};
let hash2 = {
let x: &str = "abc";
let mut hasher = DefaultHasher::new();
x.hash(&mut hasher);
hasher.finish()
};
assert!(hash1 == hash2);
}
Я пишу код, который использует это поведение в raw_entry
API HashMap
. В частности, я использую HashMap, где ключи являются перечислениями, но для уменьшения избыточных выделений я хочу выполнить поиск, используя «заимствованные» версии этих перечислений.
Другими словами, в следующем коде я делаю нужна гарантия того, что оба утверждения будут успешными, независимо от используемой реализации Hasher
. Мне кажется, что это будет зависеть от гарантий, предоставляемых Hash
реализацией String
и str
.
use std::hash::Hash;
use std::hash::Hasher;
use std::collections::hash_map::DefaultHasher;
pub fn main() {
{
#[derive(Hash)]
enum E1 {
First(i32),
Second(String),
}
#[derive(Hash)]
enum E2<'a> {
First(i32),
Second(&'a str),
}
let hash1 = {
let x: E1 = E1::First(100);
let mut hasher = DefaultHasher::new();
x.hash(&mut hasher);
hasher.finish()
};
let hash2 = {
let x: E2 = E2::First(100);
let mut hasher = DefaultHasher::new();
x.hash(&mut hasher);
hasher.finish()
};
assert!(hash1 == hash2);
let hash3 = {
let x: E1 = E1::Second("abc".to_owned());
let mut hasher = DefaultHasher::new();
x.hash(&mut hasher);
hasher.finish()
};
let hash4 = {
let x: E2 = E2::Second("abc");
let mut hasher = DefaultHasher::new();
x.hash(&mut hasher);
hasher.finish()
};
assert!(hash3 == hash4);
}
}
Есть ли где-нибудь документально подтверждены такие гарантии? Я бы предположил, что такие гарантии должны быть предоставлены (в противном случае я не вижу возможности правильно реализовать метод contains_key()
для HashMap
, поскольку аргументом может быть любая заимствованная форма ключа), но я не могу найти эту гарантию задокументированной где угодно.