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.
1 post - 1 participant