In Rust, the standard collections (such as Vec<T>, HashMap<K,V>, HashSet<T>, etc.) implement the principle of owning their contents. This means that the collection owns all the objects it contains and is responsible for freeing their memory when they are removed.
For example, elements placed in a Vec<T> are moved into the vector, which then owns them:
let s = String::from("hi"); let mut v = Vec::new(); v.push(s); // s is now moved, not accessible
If the collection contains copyable values, they are copied; if they are move types, the ownership rights are transferred. You need to clone elements or the collection when you need to keep the original value in two places, for example:
let name = String::from("Olga"); let mut v = Vec::new(); v.push(name.clone()); println!("{}", name); // name is still accessible as it was cloned
What happens when inserting an element into a HashMap if a move type (e.g., String) is used as the key? Will the original key be available after passing it to HashMap::insert()?
The common incorrect answer is: "The original key will remain accessible after insertion."
In fact, the ownership of the key and value is transferred to the HashMap, and after insertion, they cannot be used without prior cloning:
let key = String::from("id"); let mut map = std::collections::HashMap::new(); map.insert(key, 42); // key is no longer accessible
Attempting to access key will result in a compilation error.
Story A developer tried to use a moved object after insertion into a Vec and got an error "value used here after move", not understanding that Vector now owns it.
Story When working with HashMap, they forgot to clone string keys, which led to their unavailability in other places, requiring significant code refactoring.
Story In one project, they tried to return a reference to an internal element in a vector beyond a function, forgetting that the reference would be invalidated when the vector size changed. This led to dangling references and a runtime crash (panic).