Rust: how to bound the lifetime of Iterator::next()? - rust

The following code doesn't compile:
struct Things {
things: Vec<usize>
}
struct ThingsIterMut<'a> {
contents: &'a mut Vec<usize>,
indices: std::slice::Iter<'a, usize>
}
impl<'a> Iterator for ThingsIterMut<'a> {
type Item = &'a mut usize;
fn next(&mut self) -> Option<Self::Item> {
match self.indices.next() {
None => None,
Some(i) => self.contents.get_mut(*i)
}
}
}
impl Things {
pub fn iter_mut<'a>(&'a mut self) -> ThingsIterMut<'a> {
ThingsIterMut {
contents: &mut self.things,
indices: self.things.iter()
}
}
}
fn main() {
println!("Hello, world!");
}
It complains:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/main.rs:16:24
|
16 | Some(i) => self.contents.get_mut(*i)
| ^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 13:5...
--> src/main.rs:13:5
|
13 | fn next(&mut self) -> Option<Self::Item> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:16:24
|
16 | Some(i) => self.contents.get_mut(*i)
| ^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 10:6...
--> src/main.rs:10:6
|
10 | impl<'a> Iterator for ThingsIterMut<'a> {
| ^^
note: ...so that the types are compatible
--> src/main.rs:13:46
|
13 | fn next(&mut self) -> Option<Self::Item> {
| ______________________________________________^
14 | | match self.indices.next() {
15 | | None => None,
16 | | Some(i) => self.contents.get_mut(*i)
17 | | }
18 | | }
| |_____^
= note: expected `std::iter::Iterator`
found `std::iter::Iterator`
Changing next to next(&'a mut self) dose not work (signature mismatch), neither does change self.contents.get_mut() to self.contents.get_mut::<'a>().
What's the correct way to address this issue?

I see two problems. The first is that your iter_mut function tries to return both a mutable and an immutable reference to self.things.
It is easier to see why the borrow checker doesn't allow this by simplifying it:
fn main() {
let mut things = vec![1, 2, 3];
let contents = &mut things;
let indices = things.iter(); // borrows self_things immutably
let things_iter_mut = (contents, indices);
}
The second problem that you are trying to return a longer reference than you pass into the next function.
struct Things<'things> {
contents: &'things mut Vec<usize>,
}
impl<'things> Things<'things> {
// This won't compile! The 'borrow lifetime is implied.
// But here you can see that the borrow might be shorter than
// what we are returning.
fn next(&'borrow mut self) -> &'things mut Vec<usize> {
self.contents
}
// This will compile. Because the returned reference lives
// just as long as the argument.
fn next(&'things mut self) -> &'things mut Vec<usize> {
self.contents
}
}

Related

Iterator next method lifetime mismatch

I'm trying to create an Iterator interface using the csv crate such that I can return a HashMap of col-name: value and am running into a lifetime error I cannot figure out.
For the code below:
use csv::{
Reader,
StringRecord,
StringRecordsIter,
};
use std::collections::HashMap;
use std::fs::File;
pub struct Handler {
pub reader: Reader<File>
}
impl Handler {
pub fn new(file: File) -> Handler {
Handler { reader: Reader::from_reader(file) }
}
}
// type Row = HashMap<String, String>;
pub struct Row<'r> {
number: usize,
fields: HashMap<&'r str, &'r str>,
}
pub struct CSVIterator<'f> {
current_row: usize,
headers: StringRecord,
records: StringRecordsIter<'f, File>,
}
impl<'f> CSVIterator<'f> {
pub fn new(handler: &'f mut Handler) -> CSVIterator<'f> {
CSVIterator {
current_row: 0,
headers: handler.reader.headers().unwrap().clone(),
records: handler.reader.records(),
}
}
}
impl<'f> Iterator for CSVIterator<'f> {
type Item = Row<'f>;
fn next(&mut self) -> Option<Self::Item> {
let next_record = self.records.next();
if next_record.is_none() {
return None;
}
let record = next_record.unwrap().unwrap();
let fields = make_fields(&record, &self.headers);
let row = Row {
number: self.current_row,
fields: fields,
};
return Some(row)
}
}
fn make_fields<'r>(
record: &'r StringRecord, header: &'r StringRecord
) -> HashMap<&'r str, &'r str> {
let mut row: HashMap<&str, &str> = HashMap::new();
for (colname, value) in header.iter().zip(record) {
row.insert(colname, value);
}
row
}
I'm getting the following error:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/csvio.rs:55:43
|
55 | let fields = make_fields(&record, &self.headers);
| ^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined here...
--> src/csvio.rs:47:13
|
47 | fn next(&mut self) -> Option<Self::Item> {
| ^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/csvio.rs:55:43
|
55 | let fields = make_fields(&record, &self.headers);
| ^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'f` as defined here...
--> src/csvio.rs:44:6
|
44 | impl<'f> Iterator for CSVIterator<'f> {
| ^^
note: ...so that the types are compatible
--> src/csvio.rs:47:46
|
47 | fn next(&mut self) -> Option<Self::Item> {
| ______________________________________________^
48 | | let next_record = self.records.next();
49 | |
50 | | if next_record.is_none() {
... |
61 | | return Some(row)
62 | | }
| |_____^
= note: expected `<CSVIterator<'f> as Iterator>`
found `<CSVIterator<'_> as Iterator>`
For more information about this error, try `rustc --explain E0495`.
I may not intuitively understand the lifetime requirements for the next method here, can someone point me in the right direction?
Thanks!

Multiple mutable borrows in Rust

I'm playing around with building a very simple stack based evaluator in Rust. I want the user to be able to define functions later, so I'm storing all operators in a HashMap with closures as values.
use std::collections::HashMap;
pub type Value = i32;
pub struct Evaluator<'a> {
stack: Vec<Value>,
ops: HashMap<String, &'a dyn FnMut(&'a mut Vec<Value>)>,
}
impl<'a> Evaluator<'a> {
pub fn new() -> Evaluator<'a> {
let stack: Vec<Value> = vec![];
let mut ops: HashMap<String, &'a dyn FnMut(&'a mut Vec<Value>)> = HashMap::new();
ops.insert("+".to_string(), &|stack: &'a mut Vec<Value>| {
if let (Some(x), Some(y)) = (stack.pop(), stack.pop()) {
stack.push(y + x);
}
});
Evaluator { stack, ops }
}
pub fn stack(&self) -> &[Value] {
&self.stack
}
pub fn eval(&'a mut self, input: &str) {
let symbols = input
.split_ascii_whitespace()
.collect::<Vec<_>>();
for sym in symbols {
if let Ok(n) = sym.parse::<i32>() {
self.stack.push(n);
} else {
let s = sym.to_ascii_lowercase();
if let Some(f) = self.ops.get(&s) {
f(&mut self.stack);
} else {
println!("error");
}
}
}
}
}
fn main() {
let mut e = Evaluator::new();
e.eval("1 2 +")
}
I'm currently getting two errors:
error[E0499]: cannot borrow `self.stack` as mutable more than once at a time
--> src/sample.rs:34:17
|
10 | impl<'a> Evaluator<'a> {
| -- lifetime `'a` defined here
...
34 | self.stack.push(n);
| ^^^^^^^^^^ second mutable borrow occurs here
...
38 | f(&mut self.stack);
| ------------------
| | |
| | first mutable borrow occurs here
| argument requires that `self.stack` is borrowed for `'a`
error[E0596]: cannot borrow `**f` as mutable, as it is behind a `&` reference
--> src/sample.rs:38:21
|
38 | f(&mut self.stack);
| ^ cannot borrow as mutable
error[E0499]: cannot borrow `self.stack` as mutable more than once at a time
--> src/sample.rs:38:23
|
10 | impl<'a> Evaluator<'a> {
| -- lifetime `'a` defined here
...
38 | f(&mut self.stack);
| --^^^^^^^^^^^^^^^-
| | |
| | `self.stack` was mutably borrowed here in the previous iteration of the loop
| argument requires that `self.stack` is borrowed for `'a`
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0499, E0596.
For more information about an error, try `rustc --explain E0499`.
My concern is the first one. I'm not sure what I'm doing wrong as I'm not borrowing them at the same time. Can I tell Rust the previous borrow (self.stack.pop()) is done? Any help appreciated.
I think I solved my problem. The thing I kept coming back to is, "What owns the closures?" In this case I'm using references, but nothing is taking ownership of the data. When I refactored (below) with Box to take ownership, it worked.
I'm curious if there is a way to do this with with just references and/or if my explanation is wrong?
Working code:
use std::collections::HashMap;
pub type Value = i32;
pub struct Evaluator {
stack: Vec<Value>,
ops: HashMap<String, Box<dyn FnMut(&mut Vec<Value>)>>,
}
impl Evaluator {
pub fn new() -> Evaluator {
let stack: Vec<Value> = vec![];
let mut ops: HashMap<String, Box<dyn FnMut(&mut Vec<Value>)>> = HashMap::new();
ops.insert("+".to_string(), Box::new(|stack: &mut Vec<Value>| {
if let (Some(x), Some(y)) = (stack.pop(), stack.pop()) {
stack.push(y + x);
}
}));
Evaluator { stack, ops }
}
pub fn stack(&self) -> &[Value] {
&self.stack
}
pub fn eval(&mut self, input: &str) {
let symbols = input
.split_ascii_whitespace()
.collect::<Vec<_>>();
for sym in symbols {
if let Ok(n) = sym.parse::<i32>() {
self.stack.push(n);
} else {
let s = sym.to_ascii_lowercase();
if let Some(f) = self.ops.get_mut(&s) {
f(&mut self.stack);
} else {
println!("error");
}
}
}
}
}
fn main() {
let mut e = Evaluator::new();
e.eval("1 2 +")
}
You have borrows with conflicting lifetimes:
You are defining a lifetime 'a for the struct in line 5: pub struct Evaluator<'a> {
In line 7, you are stating that ops is a HashMap that holds functions that receive mutable borrows for the whole duration of 'a
Then, in line 28, you are defining an eval method that holds a mutable reference to self for the whole duration of the struct ('a)
The conflict can be solved if you use two different lifetimes, since the time that an operation borrows self should be inherently shorter than the lifetime for the whole evaluation, since in eval you are running a loop and multiple invocations to the operations.
This should fix the issues mentioned above:
pub struct Evaluator<'a, 'b> {
stack: Vec<Value>,
ops: HashMap<String, &'b dyn FnMut(&'b mut Vec<Value>)>,
}
impl<'a, 'b> Evaluator<'a, 'b> {
pub fn new() -> Evaluator<'a> {
let stack: Vec<Value> = vec![];
let mut ops: HashMap<String, &'b dyn FnMut(&'b mut Vec<Value>)> = HashMap::new();

Cannot borrow as mutable in loop

I have the following code:
pub fn read_packet<'a>(buf: &'a mut [u8]) -> &'a [u8] {
loop {
read_exact(buf);
if let Some(packet) = to_packet(buf) {
return packet;
}
}
}
fn read_exact(_: &mut [u8]) {
todo!()
}
fn to_packet<'a>(_: &'a [u8]) -> Option<&'a [u8]> {
todo!()
}
I get the following error:
error[E0502]: cannot borrow `*buf` as mutable because it is also borrowed as immutable
--> src/lib.rs:3:9
|
1 | pub fn read_packet<'a>(buf: &'a mut [u8]) -> &'a [u8] {
| -- lifetime `'a` defined here
2 | loop {
3 | read_exact(buf);
| ^^^^^^^^^^^^^^^ mutable borrow occurs here
4 |
5 | if let Some(packet) = to_packet(buf) {
| --- immutable borrow occurs here
6 | return packet;
| ------ returning this value requires that `*buf` is borrowed for `'a`
I think it should work because:
The mutable borrow in read_exact completes on line 3.
If to_packet returns Some then the value is returned to the caller.
If not, the immutable borrow of to_packet is over at the end of the loop. So it is free to be taken mutable borrow of in the next iteration.
Can somebody please let me know why this doesn't work?
EDIT:
It seems like a current borrow checker limitation. I tried using Polonius in the nightly and it works fine with
RUSTFLAGS=-Zpolonius cargo +nightly check
It is a compiler limitation atm.
You could refactor to something like:
pub fn read_packet<'a>(buf: &'a mut [u8]) {
loop {
if read_exact(buf) {
break;
}
}
}
fn is_packet(a: &[u8]) -> bool {
true
}
fn read_exact<'a>(a: &'a mut [u8]) -> bool {
is_packet(a)
}
fn to_packet<'a>(_: &'a [u8]) -> Option<&'a [u8]> {
todo!()
}
fn process_packet<'a>(buf: &'a mut [u8]) {
read_packet(buf);
let _packet = to_packet(buf);
}
Playground
pub fn read_packet<'a>(buffer: &'a mut [u8]) -> &'a [u8] { |
let buf = buffer; |
loop { |
read_exact(buf); \/
if let Some(packet) = to_packet(buf) { 'a _
return packet; |
} |
} |
}
fn read_exact(_: &mut [u8]) {
todo!()
}
fn to_packet<'b>(_from: &'b [u8]) -> Option<&'b [u8]> {
todo!()
}
Compile error:
|
1 | pub fn read_packet<'a>(buffer: &'a mut [u8]) -> &'a [u8] {
| -- lifetime `'a` defined here
...
4 | read_exact(buf);
| ^^^^^^^^^^^^^^^ mutable borrow occurs here
5 | if let Some(packet) = to_packet(buf) {
| --- immutable borrow occurs here
6 | return packet;
| ------ returning this value requires that `*buf` is borrowed for `'a`
With Non Lexical Lifetime (NLL):
The return statement constrains the packet lifetime to be 'a.
If packet is 'a, so buf (to_packet) has to be also 'a.
'a is valid for the entire function. The loop makes the shared reference lifetime conflicts with the exclusive reference lifetime at the next iteration.
The conflict can be reproduced without the loop. This snippet doesn't compile for the same reason that buff is 'a. And we see that the root cause is the conditional return. Again 'a has to be valid for the entire function.
pub fn read_packet<'a>(buf: &'a mut [u8]) -> &'a [u8] {
if let Some(packet) = to_packet(buf) { 'a _
return packet; |
} |
read_exact(buf); |
return &[0]; \/
}
fn read_exact(_: &mut [u8]) {
todo!()
}
fn to_packet<'b>(_: &'b [u8]) -> Option<&'b [u8]> {
todo!()
}
Compile error:
|
1 | pub fn read_packet<'a>(buf: &'a mut [u8]) -> &'a [u8] {
| -- lifetime `'a` defined here
2 | if let Some(packet) = to_packet(buf) {
| --- immutable borrow occurs here
3 | return packet;
| ------ returning this value requires that `*buf` is borrowed for `'a`
4 | }
5 | read_exact(buf);
| ^^^^^^^^^^^^^^^ mutable borrow occurs here
With NLL, the lifetime is infered like you thought it would be.
pub fn read_packet<'a>(buffer: &'a mut [u8]) -> &'a [u8] {
let buf = buffer;
loop {
read_exact(buf);
if let Some(packet) = to_packet(buf) { 'x _
return packet; |
} \/
}
}
fn read_exact(_: &mut [u8]) {
todo!()
}
fn to_packet<'b>(_from: &'b [u8]) -> Option<&'b [u8]> {
todo!()
}

In Rust, how do I create a mutable iterator? [duplicate]

This question already has answers here:
How can I create my own data structure with an iterator that returns mutable references?
(1 answer)
How to implement Iterator yielding mutable references [duplicate]
(2 answers)
Closed 2 years ago.
I'm having difficulty with lifetimes when trying to create a mutable iterator in safe Rust.
Here is what I have reduced my problem to:
struct DataStruct<T> {
inner: Box<[T]>,
}
pub struct IterMut<'a, T> {
obj: &'a mut DataStruct<T>,
cursor: usize,
}
impl<T> DataStruct<T> {
fn iter_mut(&mut self) -> IterMut<T> {
IterMut { obj: self, cursor: 0 }
}
}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
let i = f(self.cursor);
self.cursor += 1;
self.obj.inner.get_mut(i)
}
}
fn f(i: usize) -> usize {
// some permutation of i
}
The structure of my DataStruct will never change, but I need to be able to mutate the contents of the elements stored within. For example,
let mut ds = DataStruct{ inner: vec![1,2,3].into_boxed_slice() };
for x in ds {
*x += 1;
}
The compiler is giving me an error about conflicting lifetimes for the reference I am trying to return. The lifetime it finds that I am not expecting is the scope of the next(&mut self) function.
If I try to annotate the lifetime on next(), then the compiler, instead, tells me I haven't satisfied the Iterator trait. Is this solvable in safe rust?
Here is the error:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/iter_mut.rs:25:24
|
25 | self.obj.inner.get_mut(i)
| ^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 22:5...
--> src/iter_mut.rs:22:5
|
22 | / fn next(&mut self) -> Option<Self::Item> {
23 | | let i = self.cursor;
24 | | self.cursor += 1;
25 | | self.obj.inner.get_mut(i)
26 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/iter_mut.rs:25:9
|
25 | self.obj.inner.get_mut(i)
| ^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 19:6...
--> src/iter_mut.rs:19:6
|
19 | impl<'a, T> Iterator for IterMut<'a, T> {
| ^^
note: ...so that the types are compatible
--> src/iter_mut.rs:22:46
|
22 | fn next(&mut self) -> Option<Self::Item> {
| ______________________________________________^
23 | | let i = self.cursor;
24 | | self.cursor += 1;
25 | | self.obj.inner.get_mut(i)
26 | | }
| |_____^
= note: expected `std::iter::Iterator`
found `std::iter::Iterator`
edits:
changed implementation of next() so that iteration order is a permutation of original sequence.
The borrow checker is unable to prove that subsequent calls to next() won't access the same data. The reason why this is a problem is because the lifetime of the borrow is for the duration of the life of the iterator, so it can't prove that there won't be two mutable references to the same data at the same time.
There really isn't a way to solve this without unsafe code - or changing your data structures. You could do the equlivant of slice::split_at_mut but, given that you can't mutate the original data, you'd have to implement that in unsafe code anyway. An unsafe implementation could look something like this:
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
let i = self.cursor;
self.cursor += 1;
if i < self.obj.inner.len() {
let ptr = self.obj.inner.as_mut_ptr();
unsafe {
Some(&mut *ptr.add(i))
}
} else {
None
}
}
}

Anonymous vs struct lifetime for assignment

For this code (trimmed some, sorry not more), I get a lifetime problem:
fn main() {
println!("Hello, world!");
}
#[derive(Debug)]
pub struct Token<'a> {
pub line: usize,
// Col in code points.
pub col: usize,
// Index in bytes.
pub index: usize,
pub state: TokenState,
pub text: &'a str,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum TokenState {
VSpace,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ParseState {
Expr,
}
pub struct Node<'a> {
kids: Vec<Node<'a>>,
state: ParseState,
token: Option<&'a Token<'a>>,
}
impl<'a> Node<'a> {
fn new(state: ParseState) -> Node<'a> {
Node {
kids: vec![],
state,
token: None,
}
}
fn new_token(token: &'a Token<'a>) -> Node<'a> {
// TODO Control state? Some token state?
Node {
kids: vec![],
state: ParseState::Expr,
token: Some(&token),
}
}
fn push_if(&mut self, node: Node<'a>) {
if !node.kids.is_empty() {
self.kids.push(node);
}
}
}
pub fn parse<'a>(tokens: &'a Vec<Token<'a>>) -> Node<'a> {
let mut root = Node::new(ParseState::Expr);
let mut parser = Parser {
index: 0,
tokens: tokens,
};
parser.parse_block(&mut root);
root
}
struct Parser<'a> {
index: usize,
tokens: &'a Vec<Token<'a>>,
}
impl<'a> Parser<'a> {
fn parse_block(&mut self, parent: &mut Node) {
loop {
let mut row = Node::new(ParseState::Expr);
match self.peek() {
Some(_) => {
self.parse_row(&mut row);
}
None => {
break;
}
}
parent.push_if(row);
}
}
fn parse_row(&mut self, parent: &mut Node) {
loop {
match self.next() {
Some(ref token) => match token.state {
TokenState::VSpace => break,
_ => {
parent.kids.push(Node::new_token(&token));
}
},
None => break,
}
}
}
fn next(&mut self) -> Option<&Token> {
let index = self.index;
if index < self.tokens.len() {
self.index += 1;
}
self.tokens.get(index)
}
fn peek(&mut self) -> Option<&Token> {
self.tokens.get(self.index)
}
}
(playground)
This is the error message:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:90:24
|
90 | match self.next() {
| ^^^^
|
note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 72:1...
--> src/main.rs:72:1
|
72 | / impl<'a> Parser<'a> {
73 | | fn parse_block(&mut self, parent: &mut Node) {
74 | | loop {
75 | | let mut row = Node::new(ParseState::Expr);
... |
112| | }
113| | }
| |_^
note: ...so that the type `Parser<'a>` is not borrowed for too long
--> src/main.rs:90:19
|
90 | match self.next() {
| ^^^^
note: but, the lifetime must be valid for the anonymous lifetime #3 defined on the method body at 88:5...
--> src/main.rs:88:5
|
88 | / fn parse_row(&mut self, parent: &mut Node) {
89 | | loop {
90 | | match self.next() {
91 | | Some(ref token) => match token.state {
... |
99 | | }
100| | }
| |_____^
note: ...so that expression is assignable (expected Node<'_>, found Node<'_>)
--> src/main.rs:94:42
|
94 | parent.kids.push(Node::new_token(&token));
| ^^^^^^^^^^^^^^^^^^^^^^^
All the references should be tied to the same outside lifetime. In my full code (of which I just have an excerpt here), I expect to hang onto the original parsed source, and I'm trying to tie everything to that.
I know the error messages are trying to be helpful, but I'm really unsure what the conflict is. And I'm unsure what other lifetime questions here are related to the same issue I have or not.
Let's take a look at the signature of Parser::next:
fn next(&mut self) -> Option<&Token>
This function promises to return an Option<&Token>. There are elided lifetimes here; let's rewrite the signature to make them explicit:
fn next<'b>(&'b mut self) -> Option<&'b Token<'b>>
We can now see that next is generic over lifetime 'b. Notice how the return type uses 'b, not 'a. This is valid in itself, because the compiler can infer that 'b is a shorter than 'a, and mutable references (&'a mut T) are covariant over 'a ("covariant" in this context means that we can substitute lifetime 'a with a shorter lifetime). But what the function ends up promising is that the result lives at least as long as itself, while it can in fact live at least as long as 'a.
In Parser::parse_row, you're trying to take the result of Parser::next and insert it into parent. Let's look at Parser::parse_row's signature:
fn parse_row(&mut self, parent: &mut Node)
We have some omitted lifetimes here again. Let's spell them out:
fn parse_row<'b, 'c, 'd>(&'b mut self, parent: &'c mut Node<'d>)
'c is not going to be important, so we can ignore it.
If we try to compile now, the last two notes are different:
note: but, the lifetime must be valid for the lifetime 'd as defined on the method body at 88:5...
--> src/main.rs:88:5
|
88 | / fn parse_row<'b, 'c, 'd>(&'b mut self, parent: &'c mut Node<'d>) {
89 | | loop {
90 | | match self.next() {
91 | | Some(ref token) => match token.state {
... |
99 | | }
100| | }
| |_____^
note: ...so that expression is assignable (expected Node<'d>, found Node<'_>)
--> src/main.rs:94:42
|
94 | parent.kids.push(Node::new_token(&token));
| ^^^^^^^^^^^^^^^^^^^^^^^
Now, one of the anonymous lifetimes is identified as 'd. The other is still an anonymous lifetime, and that's an artifact of how the compiler manipulates lifetimes, but we can think of it as being 'b here.
The problem should be a bit clearer now: we're trying to push a Node<'b> into a collection of Node<'d> objects. It's important that the type be exactly Node<'d>, because mutable references (&'a mut T) are invariant over T ("invariant" means it can't change).
Let's make the lifetimes match. First, we'll change next's signature to match what we can actually return:
fn next(&mut self) -> Option<&'a Token<'a>>
This means that now, when we call self.next() in parse_row, we'll be able to construct a Node<'a>. A Node<'x> can only store Node<'x> objects (per your definition of Node), so the parent parameter's referent must also be of type Node<'a>.
fn parse_row(&mut self, parent: &mut Node<'a>)
If we try to compile now, we'll get an error in Parser::parse_block on the call to parse_row. The problem is similar to what we just saw. parse_block's signature is:
fn parse_block(&mut self, parent: &mut Node)
which expands to:
fn parse_block<'b, 'c, 'd>(&'b mut self, parent: &'c mut Node<'d>)
Here's the error the compiler gives with this elaborated signature:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src/main.rs:78:26
|
78 | self.parse_row(&mut row);
| ^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 72:1...
--> src/main.rs:72:1
|
72 | / impl<'a> Parser<'a> {
73 | | fn parse_block<'b, 'c, 'd>(&'b mut self, parent: &'c mut Node<'d>) {
74 | | loop {
75 | | let mut row = Node::new(ParseState::Expr);
... |
112| | }
113| | }
| |_^
note: ...so that types are compatible (expected &mut Parser<'_>, found &mut Parser<'a>)
--> src/main.rs:78:26
|
78 | self.parse_row(&mut row);
| ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'd as defined on the method body at 73:5...
--> src/main.rs:73:5
|
73 | / fn parse_block<'b, 'c, 'd>(&'b mut self, parent: &'c mut Node<'d>) {
74 | | loop {
75 | | let mut row = Node::new(ParseState::Expr);
76 | | match self.peek() {
... |
85 | | }
86 | | }
| |_____^
note: ...so that types are compatible (expected &mut Node<'_>, found &mut Node<'d>)
--> src/main.rs:84:20
|
84 | parent.push_if(row);
| ^^^^^^^
The compiler is unable to infer the type of row (specifically, the lifetime in its type Node<'x>). On one hand, the call to parse_row means it should be Node<'a>, but the call to push_if means it should be Node<'d>. 'a and 'd are unrelated, so the compiler doesn't know how to unify them.
The solution is easy, and it's the same as above: just make parent have type &mut Node<'a>.
fn parse_block(&mut self, parent: &mut Node<'a>)
Now your code compiles!

Resources