Get ref to last inserted element

I want to get a reference to the inserted element in my HashMap. I know this has been posted many times but I can't see a solution there...

pub struct PropertyGraph<'graph> {
    v: HashMap<VertexId, PropertyVertex<'graph>>
}

impl<'graph> PropertyGraph<'graph> {
     pub fn add_vertex(&mut self) -> &'graph PropertyVertex<'graph> {
       let id = self.next_vertex_id();
       let new_vertex = PropertyVertex::new(id);
       self.v.insert(id, new_vertex);
       &self.v[&id]
    }
}

Wich leads to the following error:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
   --> src/graph_engine/graph.rs:186:10
    |
186 |         &self.v[&id]
    |          ^^^^^^^^^^^
    |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 182:5...
   --> src/graph_engine/graph.rs:182:5
    |
182 | /     pub fn add_vertex(&mut self) -> &'graph PropertyVertex<'graph> {
183 | |         let id = self.next_vertex_id();
184 | |         let new_vertex = PropertyVertex::new(id);
185 | |         self.v.insert(id, new_vertex);
186 | |         &self.v[&id]
187 | |     }
    | |_____^
note: ...so that reference does not outlive borrowed content
   --> src/graph_engine/graph.rs:186:10
    |
186 |         &self.v[&id]
    |          ^^^^^^
note: but, the lifetime must be valid for the lifetime `'graph` as defined on the impl at 140:6...
   --> src/graph_engine/graph.rs:140:6
    |
140 | impl<'graph> PropertyGraph<'graph> {
    |      ^^^^^^
note: ...so that reference does not outlive borrowed content
   --> src/graph_engine/graph.rs:186:9
    |
186 |         &self.v[&id]
    |         ^^^^^^^^^^^^

error: aborting due to previous error

The strange part for me is note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 182:5... because after the insert the graph should be owning the data and I'm simply trying to return a reference to the data owned by the graph.

When you define a struct with a lifetime parameter like this:

struct PropertyGraph<'graph> { ... }

you are saying "The PropertyGraph<'graph> type contains references that are stored in another container somewhere else, and the lifetime 'graph refers to things stored in this other thing". So when you return a reference with lifetime 'graph, you are saying "This reference does not point into the PropertyGraph, but it points to whatever external storage the 'graph lifetime corresponds to".

Your code fails to compile because this is not the case. Your vertex object is stored in the hash map, which is inside the PropertyGraph, and not the external storage location that 'graph refers to. To claim that the returned reference points into self, you can do this instead:

fn add_vertex<'a>(&'a mut self) -> &'a PropertyVertex<'graph>
// which can be simplified to
fn add_vertex(&mut self) -> &PropertyVertex<'graph>

I don't have your full code, so I don't know if this would compile, but yeah. Note that additionally the references you have inside your PropertyVertex<'graph> type must point to outside of the PropertyGraph object, and can't e.g. point to other verticies in the same graph object for the same reasons as above.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.