Reputation: 1014
I wanted to create a data structure similar to the one found in this post. So, a tree of Database
nodes that contain some data associated with that node, as well as a node at a further depth.
The difference is that I want to allow the possibility of children
being None
, to indicate that the node is a leaf.
So it should look like:
{
"1": Database {
{
data: "element 1",
children: Some({
"a": Database {
data: "element 1-a",
children: None
},
"b": Database {
data: "element 1-b",
children: None
}
})
}
},
"2": Database {
{
data: "element 2",
children: None
}
}
}
Using the code in the original post, I've come up with this [playground link]:
#[derive(Default, Debug)]
struct Database {
children: Option<HashMap<String, Database>>,
data: String,
}
impl Database {
fn insert_path(&mut self, path: &[&str]) -> &mut Self {
let mut node = self;
for &subkey in path.iter() {
if let None = node.children {
node.children = Some(HashMap::new());
}
node = node
.children
.unwrap()
.entry(subkey.to_string())
.or_insert_with(Database::default);
}
node
}
}
fn main() {
let mut db = Database {
children: Some(HashMap::new()),
data: "root".to_string(),
};
let node = db.insert_path(&vec!["key1", "key1.1", "key1.1.3"]);
node.data = "myvalue".to_string();
println!("{:#?}", db);
}
This doesn't work. I get the following errors:
error[E0507]: cannot move out of `node.children` which is behind a mutable reference
--> src/main.rs:18:20
|
18 | node = node
| ____________________^
19 | | .children
| |_________________________^ move occurs because `node.children` has type `Option<HashMap<String, Database>>`, which does not implement the `Copy` trait
|
help: consider borrowing the `Option`'s content
|
18 | node = node
19 | .children.as_ref()
|
error[E0515]: cannot return value referencing temporary value
--> src/main.rs:24:9
|
18 | node = node
| ____________________-
19 | | .children
20 | | .unwrap()
| |_________________________- temporary value created here
...
24 | node
| ^^^^ returns a value referencing data owned by the current function
I'm very confused as to why this is happening. I think that using unwrap()
on node.children
drops the moved value node.children
. However, I can't see how to do this without using unwrap()
. How might I be able to achieve the functionality from the original post with this new structure that uses None
? Is this even possible?
Note: I've also chopped down the original, so that it is more similar to the above code and easier to compare. See here for a playground link.
Upvotes: 2
Views: 545
Reputation: 2618
Your example compiles if you add an as_mut()
after children
, i.e.:
node = node
.children
.as_mut()
.unwrap()
.entry(subkey.to_string())
.or_insert_with(Database::default);
Option::as_mut
turns an Option<T>
into an Option<&mut T>
, thus preventing the move out of node
when you unwrap()
node.children
.
Upvotes: 4