I'm creating a custom data structure in Rust and trying to implement iterators for it. Following the example of the built-in collections (LinkedList
, Vec
, etc), I've created an IntoIter
struct that iterates over an owned collection, an Iter
struct that iterates over a borrowed collection, and an IterMut
struct that iterates over a mutably borrowed collection.
I was able to implement the first two iterators but I'm having trouble pleasing the borrow-checker with IterMut
. I've cut my code down to the bare minimum repro and replaced my custom data structure with Vec<Option<T>>
:
pub struct IterMut<'a, T: 'a> {
list: &'a mut Vec<Option<T>>,
}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<&'a mut T> {
let head_node = &mut self.list[0];
// convert &mut Option<T> to Option<&mut T>
head_node.as_mut()
}
}
It fails to compile with
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/main.rs:23:24
|
23 | let head_node = &mut self.list[0];
| ^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 22:2...
--> src/main.rs:22:2
|
22 | / fn next(&mut self) -> Option<&'a mut T> {
23 | | let head_node = &mut self.list[0];
24 | | // convert &mut Option<T> to Option<&mut T>
25 | | head_node.as_mut()
26 | | }
| |__^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:23:24
|
23 | let head_node = &mut self.list[0];
| ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 19:1...
--> src/main.rs:19:1
|
19 | / impl<'a, T> Iterator for IterMut<'a, T> {
20 | | type Item = &'a mut T;
21 | |
22 | | fn next(&mut self) -> Option<&'a mut T> {
... |
26 | | }
27 | | }
| |_^
note: ...so that expression is assignable (expected std::option::Option<&'a mut T>, found std::option::Option<&mut T>)
--> src/main.rs:25:3
|
25 | head_node.as_mut()
| ^^^^^^^^^^^^^^^^^^
What really confuses me about this is that this code is almost identical to the code I used for Iter
, which compiles successfully:
pub struct Iter<'a, T: 'a> {
list: &'a Vec<Option<T>>,
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> {
let head_node = &self.list[0];
// convert &Option<T> to Option<&T>
head_node.as_ref()
}
}
I know that &
and &mut
are two different things, but I thought their lifetimes would still be calculated the same way. My first guess was that as_ref()
must be somehow different than as_mut()
but there doesn't appear to be a difference in the source code of their implementations (as_ref, as_mut).
What is the borrow-checker complaining about?