Я использую сложный ключ для HashMap, так что ключ состоит из двух частей, а одна часть - String, и я не могу понять, как выполнять поиск с помощью метода HashMap::get не выделяя новую String для каждого поиска.
Вот какой код:
#[derive(Debug, Eq, Hash, PartialEq)]
struct Complex {
    n: i32,
    s: String,
}
impl Complex {
    fn new<S: Into<String>>(n: i32, s: S) -> Self {
        Complex { n: n, s: s.into() }
    }
}
fn main() {
    let mut m = std::collections::HashMap::<Complex, i32>::new();
    m.insert(Complex::new(42, "foo"), 123);
    // OK, but allocates temporary String
    assert_eq!(123, *m.get(&Complex::new(42, "foo")).unwrap());
}
 Проблема заключается в конечном утверждении. Он проходит, но для этого требуется временное распределение кучи, потому что я не могу построить Complex без построения String.
 Чтобы устранить временные распределения, подобные этому, Rust предоставляет свойство  Borrow, которое использует метод HashMap::get. Я понимаю, как заставить работу Borrow простые ключи. Например, Rust Standard Library PathBuf реализует Borrow<Path>, используя std::mem::transmute под капотом, но я не могу понять, как заставить его работать для моего типа Complex:
#[derive(Debug)]
struct Borrowable {
    // ??? -- What goes here? Perhaps something like:
    n: i32,
    s1: &str, // ??? -- But what would the lifetime be? Or maybe:
    s2: str,  // ??? -- But how would I extend this to a complex type
              //        containing two or more strings?
}
impl Borrowable {
    fn new(n: i32, s: &str) -> &Self {
         // ??? -- What goes here? It must not allocate.
        unimplemented!();
    }
}
impl std::borrow::Borrow<Borrowable> for Complex {
    fn borrow(&self) -> &Borrowable {
        // ??? -- What goes here? How can I transmute a Complex into a
        //        &Borrowable?
        unimplemented!();
    }
}
 Это похоже на обычный случай использования, и я подозреваю, что мне не хватает чего-то важного для Borrow, но у меня полная потеря.
