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.
Related
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.
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.
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.
This code compiles:
struct BufRef<'a> {
buf: &'a [u8],
}
struct Foo<'a> {
buf_ref: BufRef<'a>,
}
impl<'a> Iterator for Foo<'a> {
type Item = &'a [u8];
fn next(&mut self) -> Option<Self::Item> {
let result = &self.buf_ref.buf;
Some(result)
}
}
However, if I change BufRef to:
struct BufRef<'a> {
buf: &'a mut [u8],
}
The compiler says:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src\main.rs:13:16
|
13 | let result = &self.buf_ref.buf;
| ^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 12:5...
--> src\main.rs:12:5
|
12 | / fn next(&mut self) -> Option<Self::Item> {
13 | | let result = &self.buf_ref.buf;
14 | | Some(result)
15 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src\main.rs:13:16
|
13 | let result = &self.buf_ref.buf;
| ^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 9:6...
--> src\main.rs:9:6
|
9 | impl<'a> Iterator for Foo<'a> {
| ^^
= note: ...so that the types are compatible:
expected std::iter::Iterator
found std::iter::Iterator
Why does changing the field to &'a mut [u8] cause the error?
Also, what does the compiler mean by this:
...so that the types are compatible:
expected std::iter::Iterator
found std::iter::Iterator
I think that what is misleading you is that your code has a collapsed reference.
Your next function is basically equivalent to this code:
fn next(&mut self) -> Option<&'a [u8]> {
let result: &&'a [u8] = &self.buf_ref.buf;
Some(result)
}
This works because the double reference collapses to a single reference. In this case the double reference only obfuscates the code. Just write:
fn next(&mut self) -> Option<Self::Item> {
Some(self.buf_ref.buf)
}
And this works because references are always Copy.
But now what happens when you change your definition to &'a mut? You are probably guessing right now... mutable references are not Copy, so the same simple code will give you an easy-to-read error message:
cannot move out of self.buf_ref.buf which is behind a mutable reference
Naturally, you can reborrow a mutable ref as a const one, and then try to return it, but unfortunately this will not work because the the re-borrow cannot use the same lifetime as the mutable variable, it must be strictly smaller (or you could alias the pointed values). The compiler assigns the lifetime of this re-borrow as that of the next function, but now you cannot return this borrow, because it is a local reference!
Unfortunately, I don't know of any safe way to make your code compile. In fact I'm quite sure that it would create an unsound API. That is, if you managed to compile your code, then this safe code would create undefined behavior:
fn main() {
let mut buf = vec![1,2,3];
let buf_ref = BufRef { buf: &mut buf };
let mut foo = Foo { buf_ref };
let x: &[u8] = foo.next().unwrap();
//note that x's lifetime is that of buf, foo is not borrowed
//x and foo.buf_ref.buf alias the same memory!
//but the latter is mutable
println!("{}", x[0]); //prints 1
foo.buf_ref.buf[0] = 4;
println!("{}", x[0]); //prints what?
}
While coding along to get used to Rust, I stumbled upon a compiler error. I want to understand why I get the error and what to do about it:
cannot infer an appropriate lifetime for lifetime parameter in generic
type due to conflicting requirements
I've been looking at a lot of questions covering similar errors, but most seem related to cyclic dependencies and I don't think this is what's going on here.
This is my attempt at a MWE, which still might be further reducible:
Playground link (slightly different error message)
pub struct InnerMut<T> {
state: u32,
stored_fn: fn(&mut T, u32),
}
impl<T> InnerMut<T> {
pub fn new(stored_fn: fn(&mut T, u32)) -> InnerMut<T> {
return InnerMut {
state: std::u32::MAX,
stored_fn,
};
}
pub fn mutate(&mut self, data: &mut T) {
(self.stored_fn)(data, self.state);
self.state -= 1;
}
}
pub struct StoreFnMut<F>
where
F: FnMut(&mut [u8]),
{
mutable_closure: F,
}
impl<F> StoreFnMut<F>
where
F: FnMut(&mut [u8]),
{
pub fn new(mutable_closure: F) -> StoreFnMut<F> {
StoreFnMut { mutable_closure }
}
fn run_closure_on_mutable_borrow(&mut self) {
let mut buf = vec![0; 100];
(self.mutable_closure)(&mut buf[..]);
}
}
fn foo(borrow: &mut &mut [u8], val: u32) {
borrow[0] = (val & 0xff) as u8;
}
fn main() {
let mut capturing_closure;
let mut store_fn_mut;
let mut inner_mut;
inner_mut = InnerMut::new(foo);
capturing_closure = move |mut borrow: &mut [u8]| {
inner_mut.mutate(&mut borrow);
};
store_fn_mut = StoreFnMut::new(capturing_closure);
store_fn_mut.run_closure_on_mutable_borrow();
}
I get this helpful looking yet confusing error message when compiling with Rust 1.24.1:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements
--> src/main.rs:48:31
|
48 | inner_mut = InnerMut::new(foo);
| ^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 49:25...
--> src/main.rs:49:25
|
49 | capturing_closure = move |mut borrow: &mut [u8]| {
| _________________________^
50 | | inner_mut.mutate(&mut borrow);
51 | | };
| |_____^
note: ...so that expression is assignable (expected &mut &mut [u8], found &mut &mut [u8])
--> src/main.rs:50:26
|
50 | inner_mut.mutate(&mut borrow);
| ^^^^^^^^^^^
note: but, the lifetime must be valid for the block suffix following statement 2 at 46:5...
--> src/main.rs:46:5
|
46 | / let mut inner_mut;
47 | |
48 | | inner_mut = InnerMut::new(foo);
49 | | capturing_closure = move |mut borrow: &mut [u8]| {
... |
53 | | store_fn_mut.run_closure_on_mutable_borrow();
54 | | }
| |_^
note: ...so that variable is valid at time of its declaration
--> src/main.rs:46:9
|
46 | let mut inner_mut;
| ^^^^^^^^^^^^^
I can't possibly think of use case for &mut &mut _.
If you change foo to
fn foo(borrow: &mut [u8], val: u32);
Then you get another error:
error[E0277]: the trait bound `[u8]: std::marker::Sized` is not satisfied
--> src/main.rs:46:25
|
46 | let mut inner_mut = InnerMut::new(foo);
| ^^^^^^^^^^^^^ `[u8]` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[u8]`
note: required by `<InnerMut<T>>::new`
Well, nothing requires T to be Sized in this code as it's only used in references, so let's add the constraint T: ?Sized:
pub struct InnerMut<T: ?Sized> {
state: u32,
stored_fn: fn(&mut T, u32),
}
impl<T: ?Sized> InnerMut<T> {
// …
}
And this works.
What you are experiencing is that the compiler cannot prove that you are not storing a reference to &mut borrow inside mutate() into your InnerMut instance. This would be problematic as for all it knows the parameter to your closure lives shorter than the closure itself. But InnerMut was moved to the closure and must live longer than borrow.
Basically Rust prevents closure arguments from escaping the closure because it does not know how to infer lifetimes then.
Consider this minimal example:
struct Test<T> {
field: fn(T),
}
impl<T> Test<T> {
fn foo(&self, _val: T) {}
}
fn calc(_: &mut i32) {}
fn main() {
let test: Test<&mut i32> = Test { field: calc };
let _ = move |y: i32| {
test.foo(&mut y);
};
}
It is written in a way so that the compiler understands it better so we can understand the error:
error[E0597]: `y` does not live long enough
--> src/main.rs:15:23
|
15 | test.foo(&mut y);
| ^ borrowed value does not live long enough
16 | };
| - `y` dropped here while still borrowed
17 | }
| - borrowed value needs to live until here
But I do not even have fields of that type in my struct
One key principle of Rust is that your function signature is the barrier for error reporting. The function itself is checked against the signature and the callers are checked against the signature. That prevents reporting confusing errors about function bodies to the caller of functions (who did not even write them).
For all that Rust knows, your T is inferred as &mut u[8] and your mutate() captures a mutable self. That is suspicious. Better prevent that potential escape of closure variables.
But slightly changing the code makes it work
Rejecting all programs that are incorrect and accepting all programs that are correct is not decidable. Therefore Rust errs on the side of caution and rejects correct programs. Therefore some slight changes can make it possible for Rust to accept the program even if the program was correct before.
What does this mean for my code?
I really do not know the compiler well enough to answer this question. My guess is that by changing T to [u8] and the absence of explicit lifetimes from the InnerMut type the compiler can prove that your closure variables are not escaping.