И code block 1, и code block 2 в приведенном ниже коде работают, но я не знаю, почему.
В чем разница между Some(&number) и Some(number) ?
use std::collections::HashMap;
fn call(number: &str) -> &str {
match number {
"798-1364" => "We're sorry, please hang up and try again.",
"645-7689" => "Hello, what can I get for you today?",
_ => "Hi! Who is this again?"
}
}
fn main() {
let mut contacts = HashMap::new();
contacts.insert("Daniel", "798-1364");
//====== code block 1
match contacts.get(&"Daniel") {
Some(&number) => println!("Calling Daniel: {}", call(&number)),
_ => println!("Don't have Daniel's number."),
}
//====== code block 2, without '&'
match contacts.get("Daniel") {
Some(number) => println!("Calling Daniel: {}", call(number)),
_ => println!("Don't have Daniel's number."),
}
}

В contacts.get("Daniel") тип аргумента &str.
В contacts.get(&"Daniel") тип аргумента &&str.
Метод get()HashMap реализован следующим образом:
pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
self.base.get(k)
}
Когда вы передаете &&str, компилятор Rust автоматически разыменовывает &&str в &str. В результате обе ваши версии по существу эквивалентны.
В твоей match руке:
Some(&number) тип number это &str,Some(number) тип number это &&str.Опять же, из-за правил автоматического разыменования Rust, оба они по существу одинаковы.
Обратите внимание, что если бы вы написали Some(&&number), тип number был бы str и это не скомпилировалось бы с сообщением:
the size for values of type `str` cannot be known at compilation time
Но когда у вас есть &&T или даже &&&&&T, это действует так, как если бы у вас было &T.
Они эквивалентны из-за автоматического определения и соответствия эргономике.