HashMap with tuple keys

Here is one possible implementation. [playground]

use std::collections::HashMap;
use std::mem::ManuallyDrop;
use std::ptr;

fn get(map: HashMap<(String, String), i64>, a: &String, b: &String) -> Option<i64> {
    unsafe {
        // The 24-byte string headers of `a` and `b` may not be adjacent in
        // memory. Copy them (just the headers) so that they are adjacent. This
        // makes a `(String, String)` backed by the same data as `a` and `b`.
        let k = (ptr::read(a), ptr::read(b));

        // Make sure not to drop the strings, even if `get` panics. The caller
        // or whoever owns `a` and `b` will drop them.
        let k = ManuallyDrop::new(k);

        // Deref `k` to get `&(String, String)` and perform lookup.
        let v = map.get(&k);

        // Turn `Option<&i64>` into `Option<i64>`.
        v.cloned()
    }
}

fn main() {
    let mut map = HashMap::new();
    map.insert(("a".to_owned(), "b".to_owned()), 2);
    map.insert(("c".to_owned(), "d".to_owned()), 3);

    let a = "a".to_owned();
    let b = "b".to_owned();
    println!("{:?}", get(map, &a, &b));
}