Returning reference to a HashMap value in a function

I understand that a stack allocated value cannot be returned, but is it possible to return a reference to a HashMap value? If this is not possible I'll have to do another lookup in another function.

runnable code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=aa7d36a43e37da028b24cd26d3f98bde

same code pasted:

use std::cell::RefCell;
use std::collections::HashMap;

struct File();
struct FS {
    files: RefCell<HashMap<u64, File>>
}

impl FS {
    fn new() -> FS {
        FS {
            files: RefCell::new(HashMap::<u64, File>::new())
        }
    }
    
    fn return_ref_from_collection(&mut self) -> &File {
        let file = File();
        self.files.borrow_mut().insert(1, file);
        let f = self.files.borrow().get(&1).unwrap();
        // ... do thins with f
        f // => returns a value referencing data owned by the current function
        // but I think where f is referencing is not owned by this function
    }
}

fn main() {
    let mut fs = FS::new();
    fs.return_ref_from_collection();
}

You're returning a reference to a Ref that you got from borrow, which gets dropped at the end of the function's scope.

Is there a reason that you've put the files in a RefCell? Without that you could just return the reference normally.

It works fine without the RefCell: Playground

Alternately, you can use Ref::map to do your calculation inside the smart pointer returned by RefCell, and return that: Playground

I agree it's somewhat weird to put RefCell here. Anyway since you have an unique access(&mut) to the refcell so you don't need to care about shared mutability.

let map = self.file.get_mut();
map.insert(1, File);
map.get(&1).unwrap()
2 Likes

Thanks! Yes this snippet stripped some details, I need RefCell in the real logic to be able to borrow the inner HashMap as both mutable and immutable.