Sorry for posting in drips and drabs...
I've revisited the "An OK stack" chapter as well now. It's very similar to the previous one, except that it uses Option and its methods instead of rolling our own Option-like enum and implementing all functionality by hand. However, my pop_node()
implementation is causing me to wonder if I can simplify it via some methods on Option I missed in my scouring of the docs. Below follows the suggested answer which doesn't implement pop_node()
:
pub fn pop(&mut self) -> Option<T> {
self.head.take().map(|node| {
self.head = node.next;
node.elem
})
}
fn drop(&mut self) {
let mut cur_link = self.head.take();
while let Some(mut boxed_node) = cur_link {
cur_link = boxed_node.next.take();
}
}
Here is my implementation of pop()
, pop_node()
and drop()
:
pub fn pop(&mut self) -> Option<T> {
self.pop_node().map(|node| node.elem)
}
fn pop_node(&mut self) -> Link<T> {
let next = self.head.as_mut().map(|node| mem::replace(&mut node.next, None)).unwrap_or(None);
mem::replace(&mut self.head, next)
}
fn drop(&mut self) {
while let Some(_) = self.pop_node() {}
}
Another question: I tried the following:
fn pop_node(&mut self) -> Link<T> {
mem::replace(&mut self.head, self.head.as_mut().map(|node| mem::replace(&mut node.next, None)).unwrap_or(None))
}
but I get
error[E0499]: cannot borrow `self.head` as mutable more than once at a time
--> src\second.rs:32:38
|
32 | mem::replace(&mut self.head, self.head.as_mut().map(|node| mem::replace(&mut node.next, None)).unwrap_or(None))
| ------------ -------------- ^^^^^^^^^ second mutable borrow occurs
here
| | |
| | first mutable borrow occurs here
| first borrow later used by call
error: aborting due to previous error
For more information about this error, try `rustc --explain E0499`.
error[E0499]: cannot borrow `self.head` as mutable more than once at a time
--> src\second.rs:32:38
|
32 | mem::replace(&mut self.head, self.head.as_mut().map(|node| mem::replace(&mut node.next, None)).unwrap_or(None))
| ------------ -------------- ^^^^^^^^^ second mutable borrow occurs
here
| | |
| | first mutable borrow occurs here
| first borrow later used by call
error: could not compile `lists`.
To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
error: aborting due to previous error
For more information about this error, try `rustc --explain E0499`.
error: could not compile `lists`.
To learn more, run the command again with --verbose.
Is this case, where the second parameter's borrow ends before the first parameter's will be needed something that Polonius can understand? I get it is probably extremely difficult to handle this case correctly and it isn't really a problem, I'm just curious...