References are not for storing things by reference (Box is). References are for borrowing objects that already permanently live elsewhere, and locking source of that object to be read-only.

In your case vertex given to the function is owned by that function, and the function will always destroy it when it ends. But you want that soon-to-be-destroyed object without a permanent home to be temporarily borrowed inside self.vertices that lives longer than this function call.

If all Vertex objects are already stored elsewhere, outside of Graph and statically guarantee to always outlive Graph (in practice it means they all must have been created before Graph is created), then you can make add_vertex take a temporarily borrowed &Vertex.

otherwise take ownership of Vertex, and store actual Vertex in the HashMaps. If you want to store a pointer instead of struct, then Box<Vertex> is a plain pointer.

Now I have a better understanding why my code doesn’t work. I admit that I haven’t come across the concept of Box, and will read up on it.

It should also be the same reason why it fails when I try to pass in &Vertex to add_vertex function?
How it works it that I create a Vertex from the calling function and pass a Vertex reference to add_vertex. When the calling function ends, both self.vertices and inner_matrix contains Vertex that have already been freed.

Since I intend to store vertices and rate and next holds the reference to all the Vertex objects, I will make vertices own the Vertex object, and store the references in rate and next.

If all Vertex objects are already stored elsewhere, outside of Graph and statically guarantee to always outlive Graph (in practice it means they all must have been created before Graph is created), then you can make add_vertex take a temporarily borrowed &Vertex .

So making vertices own the Vertex, while rate and next holds a Vertex reference still wouldn’t make it.

Arc is an owning type, but has shared ownership, so the same Vertex can live in multiple hashsets/maps at the same time. By default in Rust ownership is unique — an object can exist in one place at a time only, which is how it knows when to free it.

because what if you put references from vertices into rate, and then called vertices.clear()? It’d free all vertices, and rate would end up full of dangling pointers. That’s called self-referential struct in Rust, and the borrow checker won’t allow it (the borrow checker rules guarantee you can’t make dangling pointers, and it’s not enough for the borrowcheker to have code that doesn’t make dangling pointers, but could). That’s why Arc may be needed, because it dynamically enforces you can’t make a dangling pointer.

Ok now I understood I cannot have an immutable reference to an owned mutable object while that reference is still living.

What I did is to put vertices: HashSet<Vertex> in a struct Graph, and rate, next with Arc<Vertex> in another struct GraphResult

The reason why I want to put vertices in a struct is that I want to implement methods on it.

So in main function, I instantiate both Graph and GraphResult, create a Vertex object clone it twice and store it in rate and next of GraphResult and store the original Vertex object in vertices of Graph.

I feel this isn’t using the shared references feature of Arc, because Arc will take ownership of Vertex if I just create an Arc out of Vertex

Cloning of Arc<Vertex> gives you another Arc that shares the same Vertex (the vertex isn’t copied). From Rust’s perspective you own multiple Arc objects, so you can pass them around individually, but thanks to Arc's internal reference counting, there’s only one Vertex.

But if you want to ensure there’s only one copy each vertex, then it has to be always Arc<Vertex> everywhere, so use HashSet<Arc<Vertex>>. Conversion of Vertex to Arc<Vertex> makes a copy (Vertex::clone() is a real clone, Arc::clone() is a cheap refcounting clone).

Thank you for the help kornel! I think using Arc<Vertex> for all 3 data structures should be the way if I only want a single heap allocated Vertex. I make 2 clones for Arc<Vertex> for rate and next and store the converted Arc<Vertex> from Vertex in vertices.

For some reason, I miss the fact that conversion of Arc<Vertex> from Vertex is still the ‘source of truth’ rather than just a reference.