How too loop over a function that requires a mutable refrence? - rust

I am quite new to rust and I have a problem with the borrow checker.
I have a function like this:
impl<'a> DFA<'a> {
fn solve_next(&mut self, c: Option<char>) -> Option<TokenType> {
let node = self.state.unwrap_or_else(|| &self.start_node);
let checks: Vec<char> = node.connections.iter().map(|x| x.1).collect();
let mut position = None;
if let Some(c) = c {
position = checks.iter().position(|x| *x == c);
}
if let Some(i) = position {
let node = &node.connections[i].0;
self.state = Some(node);
None
} else {
if node.is_end {
return Some(TokenType::Keyword);
}
panic!("Invalid charter for current set");
}
}
}
This function either returns a TokenType (which is a enum) when the loop is complete or None when it is not.
its is on this struct:
struct DFA<'a> {
state: Option<&'a Node>,
start_node: Node,
}
Node is:
struct Node {
connections: Vec<(Node, char)>,
is_end: bool,
token_type: TokenType,
}
with the method
fn insert(&mut self, _match: char, end: bool) -> &mut Node {
which creates and return a new node and adds this node into its own connections.
So when I wanted to loop over the solve next function I tried:
impl<'a> Lexer<'a> {
fn next_char(&self) -> Option<char> {
let mut r: Option<char> = None;
for c in &self.chars {
match c {
' ' | '\n' | '\r' => {
continue;
}
_ => {
r = Some(c.clone());
break;
}
}
}
return r;
}
fn next_token(&'a mut self) {
let somechar = 'c';
let mut x = self.dfa.solve_next(self.next_char());
while let None = x {
x = self.dfa.solve_next(self.next_char());
}
}
}
which is a method of
struct Lexer<'a> {
//the output of the lexer
pub tokens: Vec<Token>,
chars: Vec<char>,
dfa: DFA<'a>,
}
the compile error's with
error[E0499]: cannot borrow `self.dfa` as mutable more than once at a time
--> src/main.rs:177:17
|
146 | impl<'a> Lexer<'a> {
| -- lifetime `'a` defined here
...
175 | let mut x = self.dfa.solve_next(self.next_char());
| -------------------------------------
| |
| first mutable borrow occurs here
| argument requires that `self.dfa` is borrowed for `'a`
176 | while let None = x {
177 | x = self.dfa.solve_next(self.next_char());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
--> src/main.rs:177:37
|
146 | impl<'a> Lexer<'a> {
| -- lifetime `'a` defined here
...
175 | let mut x = self.dfa.solve_next(self.next_char());
| -------------------------------------
| |
| mutable borrow occurs here
| argument requires that `self.dfa` is borrowed for `'a`
176 | while let None = x {
177 | x = self.dfa.solve_next(self.next_char());
| ^^^^^^^^^^^^^^^^ immutable borrow occurs here
So is their any way I can use solve_next in this loop? as I would not know how to make a function that can be used like this without having it take a mutable refrence.

The actual error you get with your code is the following (playground):
error: lifetime may not live long enough
--> src/lib.rs:27:49
|
25 | impl<'a> DFA<'a> {
| -- lifetime `'a` defined here
26 | fn solve_next(&mut self, c: Option<char>) -> Option<TokenType> {
| - let's call the lifetime of this reference `'1`
27 | let node = self.state.unwrap_or_else(|| &self.start_node);
| ^^^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
This is actually complaining about the reference to self.start_node not living long enough, that is for at least 'a.
The reason for that is that your local variable node, that is of type &'x Node, being the lifetime 'x the shorter of that of self.state.unwrap() and &self.start_node. The first one is 'a and the second one is the unnamed lifetime of &self (from now on 's).
But by the rules of Rust lifetimes, 'a outlives DFA<'a> and Self outlives 's, and Self is equal to DFA<'a>, then we conclude that 'a outlives 's. So the lifetime of the local node is actually 's.
Now, the other key line is this one:
self.state = Some(node);
being self.state of type Option<&'a Node>, that requires that the lifetime of node, that is 's, outlives 'a. But that cannot be, we already determined that it is the other way around: 'a outlives 's. Thus a compiler error.
In a nutshell, you are trying to write a self-referential struct, storing in one field a reference to the other field. And that is well known to be impossible.
In the original version of your question, you tried to solve it adding an extra lifetime to the solve_next() function:
fn solve_next(&'a mut self, c: Option<char>) -> Option<TokenType>
Doing that you force the 's from my explanation above to be exactly equal to 'a, so the body of this function is actually correct. Unfortunately if you try to call it normally with:
fn next_token(&mut self) {
let mut x = self.dfa.solve_next(self.next_char());
}
It fails with:
error: lifetime may not live long enough
--> src/lib.rs:63:21
|
46 | impl<'a> Lexer<'a> {
| -- lifetime `'a` defined here
...
62 | fn next_token(&mut self) {
| - let's call the lifetime of this reference `'1`
63 | let mut x = self.dfa.solve_next(self.next_char());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'a`
Exactly for the same reason as above: the anonymous lifetime of self must outlive 'a but the compiler deduces it the other way around.
Naturally you can fix it the same way:
fn next_token(&'a mut self) {
And that will compile... as long as you do not try to call solve_next() twice.
I'm not sure why calling solve_next() once it compiles, but calling it twice fails with. But it does not actually matter because even if this function worked, with this extra &'a mut self you'd still have the same problem calling this function from the external code.
What about the solution? Well, I think you need to refactor the code so that you never try to add a reference start_node in the same struct.
For example, you can store the start_node outside this struct:
struct DFA<'a> {
state: Option<&'a Node>,
start_node: &'a Node,
}
This, and remove all the lifetime annotations from &'a self and it will just compile (playground).

Related

Usage of `mut` keyword results in "lifetime may not live long enough" error, when it does [duplicate]

I have created a data structure in Rust and I want to create iterators for it. Immutable iterators are easy enough. I currently have this, and it works fine:
// This is a mock of the "real" EdgeIndexes class as
// the one in my real program is somewhat complex, but
// of identical type
struct EdgeIndexes;
impl Iterator for EdgeIndexes {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
Some(0)
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
}
pub struct CGraph<E> {
nodes: usize,
edges: Vec<E>,
}
pub struct Edges<'a, E: 'a> {
index: EdgeIndexes,
graph: &'a CGraph<E>,
}
impl<'a, E> Iterator for Edges<'a, E> {
type Item = &'a E;
fn next(&mut self) -> Option<Self::Item> {
match self.index.next() {
None => None,
Some(x) => Some(&self.graph.edges[x]),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.index.size_hint()
}
}
I want to create a iterator that returns mutable references as well. I've tried doing this, but can't find a way to get it to compile:
pub struct MutEdges<'a, E: 'a> {
index: EdgeIndexes,
graph: &'a mut CGraph<E>,
}
impl<'a, E> Iterator for MutEdges<'a, E> {
type Item = &'a mut E;
fn next(&mut self) -> Option<&'a mut E> {
match self.index.next() {
None => None,
Some(x) => self.graph.edges.get_mut(x),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.index.size_hint()
}
}
Compiling this results in the following error:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/lib.rs:54:24
|
54 | Some(x) => self.graph.edges.get_mut(x),
| ^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 51:5...
--> src/lib.rs:51:5
|
51 | / fn next(&mut self) -> Option<&'a mut E> {
52 | | match self.index.next() {
53 | | None => None,
54 | | Some(x) => self.graph.edges.get_mut(x),
55 | | }
56 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:54:24
|
54 | Some(x) => self.graph.edges.get_mut(x),
| ^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 48:6...
--> src/lib.rs:48:6
|
48 | impl<'a, E> Iterator for MutEdges<'a, E> {
| ^^
= note: ...so that the expression is assignable:
expected std::option::Option<&'a mut E>
found std::option::Option<&mut E>
I'm unsure how to interpret these errors and how to change my code in order to allow MutEdges to return mutable references.
Link to playground with code.
You can't compile this because mutable references are more restrictive than immutable references. A shortened version that illustrates the issue is this:
struct MutIntRef<'a> {
r: &'a mut i32
}
impl<'a> MutIntRef<'a> {
fn mut_get(&mut self) -> &'a mut i32 {
&mut *self.r
}
}
fn main() {
let mut i = 42;
let mut mir = MutIntRef { r: &mut i };
let p = mir.mut_get();
let q = mir.mut_get();
println!("{}, {}", p, q);
}
Which produces the same error:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:7:9
|
7 | &mut *self.r
| ^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 6:5...
--> src/main.rs:6:5
|
6 | / fn mut_get(&mut self) -> &'a mut i32 {
7 | | &mut *self.r
8 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:7:9
|
7 | &mut *self.r
| ^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 5:6...
--> src/main.rs:5:6
|
5 | impl<'a> MutIntRef<'a> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:7:9
|
7 | &mut *self.r
| ^^^^^^^^^^^^
If we take a look at the main function, we get two mutable references called p and q that both alias the memory location of i. This is not allowed. In Rust, we can't have two mutable references that alias and are both usable. The motivation for this restriction is the observation that mutation and aliasing don't play well together with respect to memory safety. So, it's good that the compiler rejected the code. If something like this compiled, it would be easy to get all kinds of memory corruption errors.
The way Rust avoids this kind of danger is by keeping at most one mutable reference usable. So, if you want to create mutable reference to X based on a mutable reference to Y where X is owned by Y, we better make sure that as long as the reference to X exists, we can't touch the other reference to Y anymore. In Rust this is achieved through lifetimes and borrowing. The compiler considers the original reference to be borrowed in such a case and this has an effect on the lifetime parameter of the resulting reference as well. If we change
fn mut_get(&mut self) -> &'a mut i32 {
&mut *self.r
}
to
fn mut_get(&mut self) -> &mut i32 { // <-- no 'a anymore
&mut *self.r // Ok!
}
the compiler stops complaining about this get_mut function. It now returns a reference with a lifetime parameter that matches &self and not 'a anymore. This makes mut_get a function with which you "borrow" self. And that's why the compiler complains about a different location:
error[E0499]: cannot borrow `mir` as mutable more than once at a time
--> src/main.rs:15:13
|
14 | let p = mir.mut_get();
| --- first mutable borrow occurs here
15 | let q = mir.mut_get();
| ^^^ second mutable borrow occurs here
16 | println!("{}, {}", p, q);
| - first borrow later used here
Apparently, the compiler really did consider mir to be borrowed. This is good. This means that now there is only one way of reaching the memory location of i: p.
Now you may wonder: How did the standard library authors manage to write the mutable vector iterator? The answer is simple: They used unsafe code. There is no other way. The Rust compiler simply does not know that whenever you ask a mutable vector iterator for the next element, that you get a different reference every time and never the same reference twice. Of course, we know that such an iterator won't give you the same reference twice and that makes it safe to offer this kind of interface you are used to. We don't need to "freeze" such an iterator. If the references an iterator returns don't overlap, it's safe to not have to borrow the iterator for accessing an element. Internally, this is done using unsafe code (turning raw pointers into references).
The easy solution for your problem might be to rely on MutItems. This is already a library-provided mutable iterator over a vector. So, you might get away with just using that instead of your own custom type, or you could wrap it inside your custom iterator type. In case you can't do that for some reason, you would have to write your own unsafe code. And if you do so, make sure that
You don't create multiple mutable references that alias. If you did, this would violate the Rust rules and invoke undefined behavior.
You don't forget to use the PhantomData type to tell the compiler that your iterator is a reference-like type where replacing the lifetime with a longer one is not allowed and could otherwise create a dangling iterator.

Trying To Understand Generic Lifetime Parameters [duplicate]

I have created a data structure in Rust and I want to create iterators for it. Immutable iterators are easy enough. I currently have this, and it works fine:
// This is a mock of the "real" EdgeIndexes class as
// the one in my real program is somewhat complex, but
// of identical type
struct EdgeIndexes;
impl Iterator for EdgeIndexes {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
Some(0)
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
}
pub struct CGraph<E> {
nodes: usize,
edges: Vec<E>,
}
pub struct Edges<'a, E: 'a> {
index: EdgeIndexes,
graph: &'a CGraph<E>,
}
impl<'a, E> Iterator for Edges<'a, E> {
type Item = &'a E;
fn next(&mut self) -> Option<Self::Item> {
match self.index.next() {
None => None,
Some(x) => Some(&self.graph.edges[x]),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.index.size_hint()
}
}
I want to create a iterator that returns mutable references as well. I've tried doing this, but can't find a way to get it to compile:
pub struct MutEdges<'a, E: 'a> {
index: EdgeIndexes,
graph: &'a mut CGraph<E>,
}
impl<'a, E> Iterator for MutEdges<'a, E> {
type Item = &'a mut E;
fn next(&mut self) -> Option<&'a mut E> {
match self.index.next() {
None => None,
Some(x) => self.graph.edges.get_mut(x),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.index.size_hint()
}
}
Compiling this results in the following error:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/lib.rs:54:24
|
54 | Some(x) => self.graph.edges.get_mut(x),
| ^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 51:5...
--> src/lib.rs:51:5
|
51 | / fn next(&mut self) -> Option<&'a mut E> {
52 | | match self.index.next() {
53 | | None => None,
54 | | Some(x) => self.graph.edges.get_mut(x),
55 | | }
56 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:54:24
|
54 | Some(x) => self.graph.edges.get_mut(x),
| ^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 48:6...
--> src/lib.rs:48:6
|
48 | impl<'a, E> Iterator for MutEdges<'a, E> {
| ^^
= note: ...so that the expression is assignable:
expected std::option::Option<&'a mut E>
found std::option::Option<&mut E>
I'm unsure how to interpret these errors and how to change my code in order to allow MutEdges to return mutable references.
Link to playground with code.
You can't compile this because mutable references are more restrictive than immutable references. A shortened version that illustrates the issue is this:
struct MutIntRef<'a> {
r: &'a mut i32
}
impl<'a> MutIntRef<'a> {
fn mut_get(&mut self) -> &'a mut i32 {
&mut *self.r
}
}
fn main() {
let mut i = 42;
let mut mir = MutIntRef { r: &mut i };
let p = mir.mut_get();
let q = mir.mut_get();
println!("{}, {}", p, q);
}
Which produces the same error:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:7:9
|
7 | &mut *self.r
| ^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 6:5...
--> src/main.rs:6:5
|
6 | / fn mut_get(&mut self) -> &'a mut i32 {
7 | | &mut *self.r
8 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:7:9
|
7 | &mut *self.r
| ^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 5:6...
--> src/main.rs:5:6
|
5 | impl<'a> MutIntRef<'a> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:7:9
|
7 | &mut *self.r
| ^^^^^^^^^^^^
If we take a look at the main function, we get two mutable references called p and q that both alias the memory location of i. This is not allowed. In Rust, we can't have two mutable references that alias and are both usable. The motivation for this restriction is the observation that mutation and aliasing don't play well together with respect to memory safety. So, it's good that the compiler rejected the code. If something like this compiled, it would be easy to get all kinds of memory corruption errors.
The way Rust avoids this kind of danger is by keeping at most one mutable reference usable. So, if you want to create mutable reference to X based on a mutable reference to Y where X is owned by Y, we better make sure that as long as the reference to X exists, we can't touch the other reference to Y anymore. In Rust this is achieved through lifetimes and borrowing. The compiler considers the original reference to be borrowed in such a case and this has an effect on the lifetime parameter of the resulting reference as well. If we change
fn mut_get(&mut self) -> &'a mut i32 {
&mut *self.r
}
to
fn mut_get(&mut self) -> &mut i32 { // <-- no 'a anymore
&mut *self.r // Ok!
}
the compiler stops complaining about this get_mut function. It now returns a reference with a lifetime parameter that matches &self and not 'a anymore. This makes mut_get a function with which you "borrow" self. And that's why the compiler complains about a different location:
error[E0499]: cannot borrow `mir` as mutable more than once at a time
--> src/main.rs:15:13
|
14 | let p = mir.mut_get();
| --- first mutable borrow occurs here
15 | let q = mir.mut_get();
| ^^^ second mutable borrow occurs here
16 | println!("{}, {}", p, q);
| - first borrow later used here
Apparently, the compiler really did consider mir to be borrowed. This is good. This means that now there is only one way of reaching the memory location of i: p.
Now you may wonder: How did the standard library authors manage to write the mutable vector iterator? The answer is simple: They used unsafe code. There is no other way. The Rust compiler simply does not know that whenever you ask a mutable vector iterator for the next element, that you get a different reference every time and never the same reference twice. Of course, we know that such an iterator won't give you the same reference twice and that makes it safe to offer this kind of interface you are used to. We don't need to "freeze" such an iterator. If the references an iterator returns don't overlap, it's safe to not have to borrow the iterator for accessing an element. Internally, this is done using unsafe code (turning raw pointers into references).
The easy solution for your problem might be to rely on MutItems. This is already a library-provided mutable iterator over a vector. So, you might get away with just using that instead of your own custom type, or you could wrap it inside your custom iterator type. In case you can't do that for some reason, you would have to write your own unsafe code. And if you do so, make sure that
You don't create multiple mutable references that alias. If you did, this would violate the Rust rules and invoke undefined behavior.
You don't forget to use the PhantomData type to tell the compiler that your iterator is a reference-like type where replacing the lifetime with a longer one is not allowed and could otherwise create a dangling iterator.

Cannot infer lifetime when implementing mutable iterator [duplicate]

I have created a data structure in Rust and I want to create iterators for it. Immutable iterators are easy enough. I currently have this, and it works fine:
// This is a mock of the "real" EdgeIndexes class as
// the one in my real program is somewhat complex, but
// of identical type
struct EdgeIndexes;
impl Iterator for EdgeIndexes {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
Some(0)
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
}
pub struct CGraph<E> {
nodes: usize,
edges: Vec<E>,
}
pub struct Edges<'a, E: 'a> {
index: EdgeIndexes,
graph: &'a CGraph<E>,
}
impl<'a, E> Iterator for Edges<'a, E> {
type Item = &'a E;
fn next(&mut self) -> Option<Self::Item> {
match self.index.next() {
None => None,
Some(x) => Some(&self.graph.edges[x]),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.index.size_hint()
}
}
I want to create a iterator that returns mutable references as well. I've tried doing this, but can't find a way to get it to compile:
pub struct MutEdges<'a, E: 'a> {
index: EdgeIndexes,
graph: &'a mut CGraph<E>,
}
impl<'a, E> Iterator for MutEdges<'a, E> {
type Item = &'a mut E;
fn next(&mut self) -> Option<&'a mut E> {
match self.index.next() {
None => None,
Some(x) => self.graph.edges.get_mut(x),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.index.size_hint()
}
}
Compiling this results in the following error:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/lib.rs:54:24
|
54 | Some(x) => self.graph.edges.get_mut(x),
| ^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 51:5...
--> src/lib.rs:51:5
|
51 | / fn next(&mut self) -> Option<&'a mut E> {
52 | | match self.index.next() {
53 | | None => None,
54 | | Some(x) => self.graph.edges.get_mut(x),
55 | | }
56 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:54:24
|
54 | Some(x) => self.graph.edges.get_mut(x),
| ^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 48:6...
--> src/lib.rs:48:6
|
48 | impl<'a, E> Iterator for MutEdges<'a, E> {
| ^^
= note: ...so that the expression is assignable:
expected std::option::Option<&'a mut E>
found std::option::Option<&mut E>
I'm unsure how to interpret these errors and how to change my code in order to allow MutEdges to return mutable references.
Link to playground with code.
You can't compile this because mutable references are more restrictive than immutable references. A shortened version that illustrates the issue is this:
struct MutIntRef<'a> {
r: &'a mut i32
}
impl<'a> MutIntRef<'a> {
fn mut_get(&mut self) -> &'a mut i32 {
&mut *self.r
}
}
fn main() {
let mut i = 42;
let mut mir = MutIntRef { r: &mut i };
let p = mir.mut_get();
let q = mir.mut_get();
println!("{}, {}", p, q);
}
Which produces the same error:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:7:9
|
7 | &mut *self.r
| ^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 6:5...
--> src/main.rs:6:5
|
6 | / fn mut_get(&mut self) -> &'a mut i32 {
7 | | &mut *self.r
8 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:7:9
|
7 | &mut *self.r
| ^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 5:6...
--> src/main.rs:5:6
|
5 | impl<'a> MutIntRef<'a> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:7:9
|
7 | &mut *self.r
| ^^^^^^^^^^^^
If we take a look at the main function, we get two mutable references called p and q that both alias the memory location of i. This is not allowed. In Rust, we can't have two mutable references that alias and are both usable. The motivation for this restriction is the observation that mutation and aliasing don't play well together with respect to memory safety. So, it's good that the compiler rejected the code. If something like this compiled, it would be easy to get all kinds of memory corruption errors.
The way Rust avoids this kind of danger is by keeping at most one mutable reference usable. So, if you want to create mutable reference to X based on a mutable reference to Y where X is owned by Y, we better make sure that as long as the reference to X exists, we can't touch the other reference to Y anymore. In Rust this is achieved through lifetimes and borrowing. The compiler considers the original reference to be borrowed in such a case and this has an effect on the lifetime parameter of the resulting reference as well. If we change
fn mut_get(&mut self) -> &'a mut i32 {
&mut *self.r
}
to
fn mut_get(&mut self) -> &mut i32 { // <-- no 'a anymore
&mut *self.r // Ok!
}
the compiler stops complaining about this get_mut function. It now returns a reference with a lifetime parameter that matches &self and not 'a anymore. This makes mut_get a function with which you "borrow" self. And that's why the compiler complains about a different location:
error[E0499]: cannot borrow `mir` as mutable more than once at a time
--> src/main.rs:15:13
|
14 | let p = mir.mut_get();
| --- first mutable borrow occurs here
15 | let q = mir.mut_get();
| ^^^ second mutable borrow occurs here
16 | println!("{}, {}", p, q);
| - first borrow later used here
Apparently, the compiler really did consider mir to be borrowed. This is good. This means that now there is only one way of reaching the memory location of i: p.
Now you may wonder: How did the standard library authors manage to write the mutable vector iterator? The answer is simple: They used unsafe code. There is no other way. The Rust compiler simply does not know that whenever you ask a mutable vector iterator for the next element, that you get a different reference every time and never the same reference twice. Of course, we know that such an iterator won't give you the same reference twice and that makes it safe to offer this kind of interface you are used to. We don't need to "freeze" such an iterator. If the references an iterator returns don't overlap, it's safe to not have to borrow the iterator for accessing an element. Internally, this is done using unsafe code (turning raw pointers into references).
The easy solution for your problem might be to rely on MutItems. This is already a library-provided mutable iterator over a vector. So, you might get away with just using that instead of your own custom type, or you could wrap it inside your custom iterator type. In case you can't do that for some reason, you would have to write your own unsafe code. And if you do so, make sure that
You don't create multiple mutable references that alias. If you did, this would violate the Rust rules and invoke undefined behavior.
You don't forget to use the PhantomData type to tell the compiler that your iterator is a reference-like type where replacing the lifetime with a longer one is not allowed and could otherwise create a dangling iterator.

Why doesn't Rust let you use the innermost lifetime of nested mutable references? [duplicate]

I have created a data structure in Rust and I want to create iterators for it. Immutable iterators are easy enough. I currently have this, and it works fine:
// This is a mock of the "real" EdgeIndexes class as
// the one in my real program is somewhat complex, but
// of identical type
struct EdgeIndexes;
impl Iterator for EdgeIndexes {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
Some(0)
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
}
pub struct CGraph<E> {
nodes: usize,
edges: Vec<E>,
}
pub struct Edges<'a, E: 'a> {
index: EdgeIndexes,
graph: &'a CGraph<E>,
}
impl<'a, E> Iterator for Edges<'a, E> {
type Item = &'a E;
fn next(&mut self) -> Option<Self::Item> {
match self.index.next() {
None => None,
Some(x) => Some(&self.graph.edges[x]),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.index.size_hint()
}
}
I want to create a iterator that returns mutable references as well. I've tried doing this, but can't find a way to get it to compile:
pub struct MutEdges<'a, E: 'a> {
index: EdgeIndexes,
graph: &'a mut CGraph<E>,
}
impl<'a, E> Iterator for MutEdges<'a, E> {
type Item = &'a mut E;
fn next(&mut self) -> Option<&'a mut E> {
match self.index.next() {
None => None,
Some(x) => self.graph.edges.get_mut(x),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.index.size_hint()
}
}
Compiling this results in the following error:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/lib.rs:54:24
|
54 | Some(x) => self.graph.edges.get_mut(x),
| ^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 51:5...
--> src/lib.rs:51:5
|
51 | / fn next(&mut self) -> Option<&'a mut E> {
52 | | match self.index.next() {
53 | | None => None,
54 | | Some(x) => self.graph.edges.get_mut(x),
55 | | }
56 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:54:24
|
54 | Some(x) => self.graph.edges.get_mut(x),
| ^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 48:6...
--> src/lib.rs:48:6
|
48 | impl<'a, E> Iterator for MutEdges<'a, E> {
| ^^
= note: ...so that the expression is assignable:
expected std::option::Option<&'a mut E>
found std::option::Option<&mut E>
I'm unsure how to interpret these errors and how to change my code in order to allow MutEdges to return mutable references.
Link to playground with code.
You can't compile this because mutable references are more restrictive than immutable references. A shortened version that illustrates the issue is this:
struct MutIntRef<'a> {
r: &'a mut i32
}
impl<'a> MutIntRef<'a> {
fn mut_get(&mut self) -> &'a mut i32 {
&mut *self.r
}
}
fn main() {
let mut i = 42;
let mut mir = MutIntRef { r: &mut i };
let p = mir.mut_get();
let q = mir.mut_get();
println!("{}, {}", p, q);
}
Which produces the same error:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:7:9
|
7 | &mut *self.r
| ^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 6:5...
--> src/main.rs:6:5
|
6 | / fn mut_get(&mut self) -> &'a mut i32 {
7 | | &mut *self.r
8 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:7:9
|
7 | &mut *self.r
| ^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 5:6...
--> src/main.rs:5:6
|
5 | impl<'a> MutIntRef<'a> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:7:9
|
7 | &mut *self.r
| ^^^^^^^^^^^^
If we take a look at the main function, we get two mutable references called p and q that both alias the memory location of i. This is not allowed. In Rust, we can't have two mutable references that alias and are both usable. The motivation for this restriction is the observation that mutation and aliasing don't play well together with respect to memory safety. So, it's good that the compiler rejected the code. If something like this compiled, it would be easy to get all kinds of memory corruption errors.
The way Rust avoids this kind of danger is by keeping at most one mutable reference usable. So, if you want to create mutable reference to X based on a mutable reference to Y where X is owned by Y, we better make sure that as long as the reference to X exists, we can't touch the other reference to Y anymore. In Rust this is achieved through lifetimes and borrowing. The compiler considers the original reference to be borrowed in such a case and this has an effect on the lifetime parameter of the resulting reference as well. If we change
fn mut_get(&mut self) -> &'a mut i32 {
&mut *self.r
}
to
fn mut_get(&mut self) -> &mut i32 { // <-- no 'a anymore
&mut *self.r // Ok!
}
the compiler stops complaining about this get_mut function. It now returns a reference with a lifetime parameter that matches &self and not 'a anymore. This makes mut_get a function with which you "borrow" self. And that's why the compiler complains about a different location:
error[E0499]: cannot borrow `mir` as mutable more than once at a time
--> src/main.rs:15:13
|
14 | let p = mir.mut_get();
| --- first mutable borrow occurs here
15 | let q = mir.mut_get();
| ^^^ second mutable borrow occurs here
16 | println!("{}, {}", p, q);
| - first borrow later used here
Apparently, the compiler really did consider mir to be borrowed. This is good. This means that now there is only one way of reaching the memory location of i: p.
Now you may wonder: How did the standard library authors manage to write the mutable vector iterator? The answer is simple: They used unsafe code. There is no other way. The Rust compiler simply does not know that whenever you ask a mutable vector iterator for the next element, that you get a different reference every time and never the same reference twice. Of course, we know that such an iterator won't give you the same reference twice and that makes it safe to offer this kind of interface you are used to. We don't need to "freeze" such an iterator. If the references an iterator returns don't overlap, it's safe to not have to borrow the iterator for accessing an element. Internally, this is done using unsafe code (turning raw pointers into references).
The easy solution for your problem might be to rely on MutItems. This is already a library-provided mutable iterator over a vector. So, you might get away with just using that instead of your own custom type, or you could wrap it inside your custom iterator type. In case you can't do that for some reason, you would have to write your own unsafe code. And if you do so, make sure that
You don't create multiple mutable references that alias. If you did, this would violate the Rust rules and invoke undefined behavior.
You don't forget to use the PhantomData type to tell the compiler that your iterator is a reference-like type where replacing the lifetime with a longer one is not allowed and could otherwise create a dangling iterator.

Rust equivalent for C++ code to demonstrate protection against UAF

I am trying to understand how Rust's lifetime annotations help catch use-after-free (UAF) issues without compromising on functionality. Here is the code I have :
use std::rc::Rc;
struct Foo {
data: usize,
}
impl Foo {
pub fn begin_foo(&self) {
println!("Begin Foo");
}
pub fn end_foo(&self) {
println!("End Foo");
}
}
struct Bar {
foo: Option<Foo>,
}
impl Bar {
pub fn new(foo: Foo) -> Self {
Bar {
foo : Some(foo),
}
}
pub fn get_foo(&self) -> Option<& Foo>
{
match &self.foo {
Some(foo) => return Some(&foo),
None => return None,
}
}
}
struct FooBar<'a> {
bar : Option<Rc<Bar>>,
foo : Option<&'a Foo>,
}
impl<'a> FooBar<'a> {
pub fn new(bar : Option<Rc<Bar>>) -> Self {
FooBar {
bar : bar,
foo : None,
}
}
pub fn update_foo_1(&'a mut self)
{
if let Some(b) = &self.bar {
self.foo = b.get_foo();
}
}
// ERROR1
/*
pub fn update_foo_2(&mut self)
{
if let Some(b) = &self.bar {
self.foo = b.get_foo();
}
}
*/
pub fn invalidate_bar_1(&mut self) {
self.bar.take();
}
// Inorder to drop the RC, we have to pass self and not &self, which consumes the object.
pub fn invalidate_bar_2(self) {
if let Some(bar) = &self.bar {
println!("Strong ref count = {}", Rc::strong_count(bar));
drop(self.bar.unwrap());
}
}
pub fn use_foo(&self) {
match self.foo {
Some(foo) => println!("Foo.data = {}", foo.data),
None => println!("Foo is None"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn works()
{
println!("Works...");
let foo = Foo {data : 42};
let bar = Bar::new(foo);
let bar_rc = Rc::new(bar);
assert_eq!(1, Rc::strong_count(&bar_rc));
let mut foo_bar: FooBar = FooBar::new(Some(bar_rc));
foo_bar.update_foo_1();
foo_bar.use_foo();
foo_bar.invalidate_bar_1();
println!("Exiting works()...");
}
#[test]
fn fails()
{
println!("Fails...");
let foo = Foo {data : 42};
let bar = Bar::new(foo);
let bar_rc = Rc::new(bar);
assert_eq!(1, Rc::strong_count(&bar_rc));
let mut foo_bar: FooBar = FooBar::new(Some(bar_rc));
foo_bar.update_foo_1();
foo_bar.invalidate_bar_1();
foo_bar.use_foo();
println!("Exiting fails()...");
}
}
The requirement is that FooBar holds Bar but also a reference to Foo to avoid calling Bar::get_foo() multiple times. FooBar::invalidate_bar_*() invalidates Bar leaving the reference Foo dangling.
Given the above requirement, the following sequence of calls should be valid :
foobar.update_foo();
foobar.use_foo();
foobar.invalidate_foo();
The following is an invalid sequence of calls and must be caught at compile-time :
foobar.update_foo();
foobar.invalidate_foo();
foobar.use_foo();
But this doesn't quite happen with my code above. The challenges that I am facing are:
In FooBar::update_foo_1() I am forced to annotate self with lifetime &'a. Otherwise I get the following error :
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/lib.rs:52:26
|
52 | if let Some(b) = &self.bar {
| ^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 50:5...
--> src/lib.rs:50:5
|
50 | / pub fn update_foo_1(& mut self)
51 | | {
52 | | if let Some(b) = &self.bar {
53 | | self.foo = b.get_foo();
54 | | }
55 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:52:26
|
52 | if let Some(b) = &self.bar {
| ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 42:6...
--> src/lib.rs:42:6
|
42 | impl<'a> FooBar<'a> {
| ^^
note: ...so that the expression is assignable
--> src/lib.rs:53:24
|
53 | self.foo = b.get_foo();
| ^^^^^^^^^^^
= note: expected `std::option::Option<&'a Foo>`
found `std::option::Option<&Foo>`
When I use the &'a to resolve the above error, I cannot make any other calls that require exclusive reference to self in the same scope :
error[E0502]: cannot borrow `foo_bar` as immutable because it is also borrowed as mutable
--> src/lib.rs:104:9
|
103 | foo_bar.update_foo_1();
| ------- mutable borrow occurs here
104 | foo_bar.use_foo();
| ^^^^^^^
| |
| immutable borrow occurs here
| mutable borrow later used here
By calling this, you are making FooBar a self referential struct which is hard to define in safe rust.
pub fn update_foo_1(&'a mut self)
{
if let Some(b) = &self.bar {
self.foo = b.get_foo();
}
}
The compiler gives the error correctly here:
error[E0502]: cannot borrow `foo_bar` as immutable because it is also borrowed as mutable
--> src/lib.rs:104:9
|
103 | foo_bar.update_foo_1();
| ------- mutable borrow occurs here
104 | foo_bar.use_foo();
| ^^^^^^^
| |
| immutable borrow occurs here
| mutable borrow later used here
because if it did allow any immutable borrows after the update call, it would mean that there is no mutable borrow at that point, which also means that you can do mutable borrows after that.
What happens if the bar field's strong count was 1 and you did this:
drop(foo_bar.bar.take());
You'd have a dangling reference in the foo field of FooBar, which Rust forbids.
Rust's lifetime annotations help catch use-after-free (UAF) issues without compromising on functionality.
Rust's lifetime annotations don't "catch" anything. What they do is tell the compiler about things it may not be able to infer (namely how long borrows span).
What "catches" UAF issues is the affine type system, that is, after a move (aka taking something by value unless it's Copy), the source is inaccessible, and you can't move a structure which are active users (aka for which there are active references, all borrows must end before a structure is moved).
You're not using moves anywhere, so your FooBar object is guaranteed to always be valid.
As for the update_foo_1 issue, I think it's a logical consequence of what you're telling rust:
pub fn update_foo_1(&'a mut self)
means that method is creating a borrow which lasts all of 'a.
'a is a parameter to the structure so it needs to "outlive" the structure itself, and you're saying that you're exclusively borrowing the structure for that lifetime, which means 'a is exactly the same lifetime as the structure (which makes sense since what you're borrowing is part of the structure) and the only thing you've done is statically locked yourself out of using said structure.
Expressing graphs (/ self-referential structures) is difficult to do in Rust, and that's exactly what you're trying to do here, but more fundamentally your entire endeavour seems misguided and based on misunderstandings.

Resources