So I'm doing a silly thingy, with a HashMap keys of Vectors of references. I probably shouldn't, but am.
During the program I wanted to get user input, find the key in the hashmap that matches, and store a reference to said key. It'd be lifetime bounded to the hashmap. I read the documentation for get_key_value, and it seemed to imply that it could be used for getting a reference to the key that the hashmap owned. But I ran into borrow checker issues.
A stripped down (and now somewhat silly) example.
use std::collections::HashMap;
use std::io::{self,Write};
fn input(prompt:&str)->String{
io::stdout().write(prompt.as_bytes()).unwrap();
let mut guess=String::new();
io::stdout().flush().unwrap();
io::stdin().read_line(&mut guess).expect("Failed to read line");
guess.trim_end_matches(['\n','\r']).to_string()
}
fn main(){
let r=vec![2,3,4];
let a:HashMap<Vec<&i32>,u8>=HashMap::from_iter(r.iter().map(|a|(vec![a],1)));
let mut c1=None;
{
let b:i32=input("Key:").parse().expect("That wasn't an i32");
if let Some(aa)=a.get_key_value(&vec![&b]){
c1=Some(aa.0);
}
else{println!("Not a key");}
}
println!("{c1:?}");
As far as I can tell, c1 should be a reference tied to a, and so it shouldn't matter that b goes out of scope.
But I got
error[E0597]: `b` does not live long enough
--> src/main.rs:18:47
|
17 | let b:i32=input("Key:").parse().expect("That wasn't an i32");
| - binding `b` declared here
18 | if let Some(aa)=a.get_key_value(&vec![&b]){
| ^^ borrowed value does not live long enough
...
22 | }
| - `b` dropped here while still borrowed
23 | println!("{c1:?}");
| -- borrow later used here
For more information about this error, try `rustc --explain E0597`.
error: could not compile `playground` (bin "playground") due to 1 previous error
I messed around with
use std::collections::HashMap;
use std::io::{self,Write};
fn input(prompt:&str)->String{
io::stdout().write(prompt.as_bytes()).unwrap();
let mut guess=String::new();
io::stdout().flush().unwrap();
io::stdin().read_line(&mut guess).expect("Failed to read line");
guess.trim_end_matches(['\n','\r']).to_string()
}
fn main(){
let r=vec![2,3,4];
let a:HashMap<Vec<&i32>,u8>=HashMap::from_iter(r.iter().map(|a|(vec![a],1)));
let mut c1=None;
{
let b:i32=input("Key:").parse().expect("That wasn't an i32");
if a.contains_key(&vec![&b]){
c1=a.get_key_value(&vec![&b]).map(|(a,_)|a);
}
else{println!("Not a key");}
}
println!("{c1:?}");
}
and the Entry API but nothing seemed to work.
I settled on
unsafe{c1=a.get_key_value(&vec![&(*(&raw const b))]).map(|(a,_)|a);}
and there doesn't seem to be an issue. But I'm unsure if what I'm doing is wrong or unsound somehow.
A few friends I asked said the K:Borrow<Q> implies that &K must outlive Q. It doesn't seem like it from the documentation.
Either way, I'm somewhat confused by the "for getting a reference to a key with the same lifetime as the collection." line in the get_key_value documentation.
Also if what I'm doing is somehow unsound through some case I can't see.