Can't appease the borrow checker


#1

I’ve been pulling my hair out trying to implement this function (playground):

type MyMap = HashMap<Foo, Bar>;
fn try_get(map: &mut MyMap, key: Foo) -> Result<&mut Bar, &mut MyMap> {
    match map.get_mut(&key) {
        Some(v) => Ok(v),
        None => Err(map)
    }
}

(I know it seems silly here, but my actual function is more complex and basically boils down to this)

I’m pretty sure this should be possible, as we don’t actually need the borrow introduced by the match in the None branch, but I can’t get the borrow checker to accept it.
I tried using an if let with early return, but this doesn’t work either…
Is there a way to express this without unsafe shenanigans?

Thanks!


#2

http://smallcultfollowing.com/babysteps/blog/2016/04/27/non-lexical-lifetimes-introduction/ should help you fix this and understand the issue.


#3

See also Rust borrow of a HashMap lasts beyond the scope it’s in?:

fn try_get(map: &mut MyMap, key: Foo) -> Result<&mut Bar, &mut MyMap> {
    if map.contains_key(&key) {
        return Ok(map.get_mut(&key).unwrap());
    }
    
    Err(map)
}

#4

Thanks, it works!
However, the code access the map twice if the key exists, is there actually no way to avoid that except waiting for NLLs?


#5

I understand that it’s a contrived example, but is there a reason to return the map back to the caller in an Err given the caller already has a handle to it? Typically you’d return a value back to the caller if they gave it to you by value(ie move), but that’s not the case here.