lifetime / borrow of nested structs error [duplicate] - rust

This question already has an answer here:
How can I create my own data structure with an iterator that returns mutable references?
(1 answer)
Closed 6 months ago.
I'm having a lifetime issue when implementing an iterator on custom struct containing borrows of vecs.
I've been trying different solutions but can't fix it by myself (I'm still a beginner) and I want to understand what is going on.
here is a playground example of my issue, that should be simple enough.
This is the example :
struct SomeData;
struct CustomIterator<'a> {
pub vec: &'a mut Vec<SomeData>,
pub index: usize,
}
struct MultipleIterator<'a> {
iter1: CustomIterator<'a>,
iter2: CustomIterator<'a>,
}
impl<'a> Iterator for MultipleIterator<'a> {
type Item = (&'a mut SomeData, &'a mut SomeData);
fn next(&mut self) -> Option<Self::Item> {
Some((
match self.iter1.vec.get_mut(self.iter1.index) {
Some(mut data) => &mut data,
None => return None,
},
match self.iter2.vec.get_mut(self.iter2.index) {
Some(mut data) => &mut data,
None => return None,
}
))
}
}
I don't unerstand why I can't borrow out of the next function, since I am borrowing the struct anyway when calling next()

This is actually quite tricky to implement safely and requires a lot of care to do correctly.
First things first though:
match self.iter1.vec.get_mut(self.iter1.index) {
Some(mut data) => &mut data,
None => return None,
},
This is a problem because Vec::get_mut already returns a Option<&mut T>. So in the Some(mut data) arm, data already is a mutable reference. When you try to return &mut data, you're trying to return a &mut &mut T which doesn't work. Instead, just do this:
match self.iter1.vec.get_mut(self.iter1.index) {
Some(data) => data,
None => return None,
},
We can tidy this up even more with the ? operator which does the same thing. I'm gonna substitute SomeData for i32 from now on to demonstrate something later.
impl<'a> Iterator for MultipleIterator<'a> {
type Item = (&'a mut i32, &'a mut i32);
fn next(&mut self) -> Option<Self::Item> {
Some((
self.iter1.vec.get_mut(self.iter1.index)?,
self.iter2.vec.get_mut(self.iter2.index)?,
))
}
}
This still doesn't work and now we're getting to the core of the problem. The signature of next is
fn next(&mut self) -> Option<(&'a mut i32, &'a mut i32)>
which can be desugared to
fn next<'b>(&'b mut self) -> Option<(&'a mut i32, &'a mut i32)>
This means that the lifetime of &mut self ('b) is completely decoupled from the lifetime of the references we return ('a). Which makes total sense. If that wasn't the case, we couldn't do
let mut v = vec![1,2,3];
let mut iter = v.iter_mut();
let next1: &mut i32 = iter.next().unwrap();
let next2: &mut i32 = iter.next().unwrap();
because the lifetime of next1 would have to be the same lifetime of iter, i.e. that of v. But you can't have multiple mutable references to v at the same time, so next2 would be illegal.
So you're getting an error because Rust only knows that self is borrowed for 'b but you're telling it that you're returning a reference with lifetime 'a which it can't verify to be true.
And for good reason, because as it stands right now, your implementation isn't safe! Let's just throw caution to the wind and tell Rust that this is okay with unsafe:
impl<'a> Iterator for MultipleIterator<'a> {
type Item = (&'a mut i32, &'a mut i32);
fn next(&mut self) -> Option<Self::Item> {
unsafe {
Some((
&mut *(self.iter1.vec.get_mut(self.iter1.index)? as *mut _),
&mut *(self.iter2.vec.get_mut(self.iter2.index)? as *mut _),
))
}
}
}
It's not important what exactly this does, it basically just tells the compiler to shut up and trust me.
But now, we can do this:
let mut v1 = vec![1, 2, 3];
let mut v2 = vec![4, 5, 6];
let mut mi = MultipleIterator {
iter1: CustomIterator {
vec: &mut v1,
index: 0,
},
iter2: CustomIterator {
vec: &mut v2,
index: 0,
},
};
let next1 = mi.next().unwrap();
let next2 = mi.next().unwrap();
assert_eq!(next1, (&mut 1, &mut 4));
assert_eq!(next2, (&mut 1, &mut 4));
*next1.0 += 1;
assert_eq!(next1, (&mut 2, &mut 4));
assert_eq!(next2, (&mut 2, &mut 4));
We have broken Rust's most important rule: never have two mutable references to the same thing at once.
This can only be safe if your Iterator implementation can never return a mutable reference to something more than once. You could increment index each time, for example (although this still requires unsafe):
impl<'a> Iterator for MultipleIterator<'a> {
type Item = (&'a mut i32, &'a mut i32);
fn next(&mut self) -> Option<Self::Item> {
let next1 = self.iter1.vec.get_mut(self.iter1.index)?;
let next2 = self.iter2.vec.get_mut(self.iter2.index)?;
self.iter1.index += 1;
self.iter2.index += 1;
// SAFETY: this is safe because we will never return a reference
// to the same index more than once
unsafe { Some((&mut *(next1 as *mut _), &mut *(next2 as *mut _))) }
}
}
Here is an interesting related read from the nomicon; the "mutable slice" example being particularly relevant to your problem.

Related

Returning References from Struct Method with Lifetimes

I am trying this code:
struct ByteIter<'a> {
remainder: &'a mut [u8],
index: usize,
}
impl<'a> ByteIter<'a> {
fn new(remainder: &'a mut [u8]) -> ByteIter<'a> {
ByteIter{remainder, index: 0}
}
fn next(&'a mut self) -> Option<&'a mut u8> {
if self.index >= self.remainder.len() {
None
} else {
let mut byte = &mut self.remainder[self.index];
self.index += 1;
Some(byte)
}
}
}
fn main() {
let mut a = [ 0x51, 0x52, 0x53, 0x54];
let mut bytes = ByteIter::new(&mut a);
{
let byte_1 = bytes.next();
}
let byte_2 = bytes.next();
}
Now, as I understand, the byte_1 was borrowed from bytes. But it's lifetime has already expired. Still when I compile this, I see the following error:
29 | let byte_2 = bytes.next();
| ^^^^^
| |
| second mutable borrow occurs here
| first borrow later used here
What is the first mutable borrow here? Shouldn't it be released when byte_1 goes out of scope?
Importantly, what should I do to fix this?
With impl<'a> ByteIter<'a>, you declare that 'a is the lifetime used in the structure, ie, it's the lifetime of the underlying slice.
Now, when you say fn next(&'a mut self) -> Option<&'a mut u8> {, you're reusing the same 'a, and you say it's the same than the returned mutable reference. You're saying that the returned lifetime is the same than the ByteIter struct content.
Remove the additional lifetime constraint and the compiler will be free to compute the appropriate lifetime:
fn next(& mut self) -> Option<& mut u8> {
if self.index >= self.remainder.len() {
None
} else {
let mut byte = &mut self.remainder[self.index];
self.index += 1;
Some(byte)
}
}

Lifetime conflicts when implementing IntoIterator to iterate over an inner collection [duplicate]

I am trying to create an mutable iterator for a vector of type: Vec<Vec<(K, V)>>
The iterator code:
pub struct IterMut<'a, K: 'a, V: 'a> {
iter: &'a mut Vec<Vec<(K, V)>>,
ix: usize,
inner_ix: usize,
}
impl<'a, K, V> Iterator for IterMut<'a, K, V> {
type Item = (&'a K, &'a mut V);
#[inline]
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
while self.iter.len() < self.ix {
while self.iter[self.ix].len() < self.inner_ix {
self.inner_ix += 1;
let (ref k, ref mut v) = self.iter[self.ix][self.inner_ix];
return Some((&k, &mut v));
}
self.ix += 1;
}
return None;
}
}
The error I get is:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/main.rs:16:42
|
16 | let (ref k, ref mut v) = self.iter[self.ix][self.inner_ix];
| ^^^^^^^^^^^^^^^^^^
|
help: consider using an explicit lifetime parameter as shown: fn next(&'a mut self) -> Option<(&'a K, &'a mut V)>
--> src/main.rs:11:5
|
11 | fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
| ^
Apparently I have lifetime problems, but I don't know how to tell the compiler that this should work.
Is this how you should implement the mutable iterator or is there a better way?
When debugging cryptic error messages, I've found it easier to try and isolate the issue as much as possible.
The first step is to break the expression into its essential constituents, let's start by splitting the indexing steps:
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
while self.iter.len() < self.ix {
while self.iter[self.ix].len() < self.inner_ix {
self.inner_ix += 1;
let outer: &'a mut Vec<_> = self.iter;
let inner: &'a mut Vec<_> = &mut outer[self.ix];
let (ref k, ref mut v) = inner[self.inner_ix];
return Some((&k, &mut v));
}
self.ix += 1;
}
return None;
}
The Index trait assumes that the lifetime of its output is linked to that of its receiver, so to get a 'a lifetime we need the receiver to have a &'a lifetime, and it propagates upward, leading to the above code.
However there's an issue here: let outer: &'a mut Vec<_> = self.iter; will not compile because mutable references are not Copy.
So, how does one get a mutable reference from a mutable reference (which must be possible since IndexMut gets a mutable reference)?
One uses re-borrowing: let outer: &'a mut Vec<_> = &mut *self.iter;.
And, oh:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> <anon>:16:45
|
16 | let outer: &'a mut Vec<_> = &mut *self.iter;
| ^^^^^^^^^^^^^^^
|
The reborrowed reference is not valid for 'a, it's valid only for the (unnamed) lifetime of self!
Why Rust? Why?
Because doing otherwise would be unsafe.
&mut T is guaranteed NOT to be aliasing, however your method could create aliasing references (if you forgot to advance the index):
#[inline]
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
let (ref k, ref mut v) = self.iter[self.ix][self.inner_ix];
return Some((&k, &mut v));
}
And even if you don't, there's not guarantee that you don't have a rewind method that would allow "stepping back".
TL;DR: You were about to step on a landmine, you were steered toward Stack Overflow instead ;)
Alright, but how do you implement the iterator!.
Well, using iterators, of course. As Shepmaster (briefly) answers, there is the equivalent in the standard library already in the guise of FlatMap. The trick is to use existing iterators for the nitty-gritty details!
Something like:
use std::slice::IterMut;
pub struct MyIterMut<'a, K: 'a, V: 'a> {
outer: IterMut<'a, Vec<(K, V)>>,
inner: IterMut<'a, (K, V)>,
}
Then you consume from inner as long as it provides items, and when empty you refill it from outer.
impl<'a, K, V> MyIterMut<'a, K, V> {
fn new(v: &'a mut Vec<Vec<(K, V)>>) -> MyIterMut<'a, K, V> {
let mut outer = v.iter_mut();
let inner = outer.next()
.map(|v| v.iter_mut())
.unwrap_or_else(|| (&mut []).iter_mut());
MyIterMut { outer: outer, inner: inner }
}
}
impl<'a, K, V> Iterator for MyIterMut<'a, K, V> {
type Item = (&'a K, &'a mut V);
#[inline]
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
loop {
match self.inner.next() {
Some(r) => return Some((&r.0, &mut r.1)),
None => (),
}
match self.outer.next() {
Some(v) => self.inner = v.iter_mut(),
None => return None,
}
}
}
}
A quick test case:
fn main() {
let mut v = vec![
vec![(1, "1"), (2, "2")],
vec![],
vec![(3, "3")]
];
let iter = MyIterMut::new(&mut v);
let c: Vec<_> = iter.collect();
println!("{:?}", c);
}
Prints:
[(1, "1"), (2, "2"), (3, "3")]
as expected, so it's not completely broken, but I wish I did not have to rely on the &[] is 'static trick (ie, that std::slice::IterMut implemented Default).
You've provided no reason that you are reimplementing the standard Iterator::flat_map, so I'd just use that and another map to remove the mutability you don't need:
fn main() {
let mut a: Vec<Vec<(u8, u8)>> = Default::default();
let c = a.iter_mut()
.flat_map(|x| x.iter_mut())
.map(|&mut (ref a, ref mut b)| (a, b))
.count();
println!("{}", c);
}
Once you have that, you can just return the iterator in one of the many ways.
#[derive(Debug, Default)]
struct Thing<K, V>(Vec<Vec<(K, V)>>);
impl<K, V> Thing<K, V> {
fn iter_mut<'a>(&'a mut self) -> Box<Iterator<Item = (&'a K, &'a mut V)> + 'a> {
Box::new(self.0
.iter_mut()
.flat_map(|x| x.iter_mut())
.map(|&mut (ref a, ref mut b)| (a, b)))
}
}
fn main() {
let mut a = Thing::<u8, u8>::default();
let c = a.iter_mut().count();
println!("{}", c);
}

Mutable borrow into two parts with cleanup

I have some object that I want to split into two parts via a mutable borrow, then combine those back together into the original object when the split references go out of scope.
The simplified example below is for a Count struct that holds a single i32, which we want to split into two &mut i32s, who are both incorporated back into the original Count when the two mutable references go out of scope.
The approach I am taking below is to use an intermediate object CountSplit which holds a mutable reference to the original Count object and has the Drop trait implemented to do the re-combination logic.
This approach feels kludgy. In particular, this is awkward:
let mut ms = c.make_split();
let (x, y) = ms.split();
Doing this in one line like let (x, y) = c.make_split().split(); is not allowed because the intermediate object must have a longer lifetime. Ideally I would be able to do something like let (x, y) = c.magic_split(); and avoid exposing the intermediate object altogether.
Is there a way to do this which doesn't require doing two let's every time, or some other way to tackle this pattern that would be more idiomatic?
#[derive(Debug)]
struct Count {
val: i32,
}
trait MakeSplit<'a> {
type S: Split<'a>;
fn make_split(&'a mut self) -> Self::S;
}
impl<'a> MakeSplit<'a> for Count {
type S = CountSplit<'a>;
fn make_split(&mut self) -> CountSplit {
CountSplit {
top: self,
second: 0,
}
}
}
struct CountSplit<'a> {
top: &'a mut Count,
second: i32,
}
trait Split<'a> {
fn split(&'a mut self) -> (&'a mut i32, &'a mut i32);
}
impl<'a, 'b> Split<'a> for CountSplit<'b> {
fn split(&mut self) -> (&mut i32, &mut i32) {
(&mut self.top.val, &mut self.second)
}
}
impl<'a> Drop for CountSplit<'a> {
fn drop(&mut self) {
println!("custom drop occurs here");
self.top.val += self.second;
}
}
fn main() {
let mut c = Count { val: 2 };
println!("{:?}", c); // Count { val: 2 }
{
let mut ms = c.make_split();
let (x, y) = ms.split();
println!("split: {} {}", x, y); // split: 2 0
// each of these lines correctly gives a compile-time error
// c.make_split(); // can't borrow c as mutable
// println!("{:?}", c); // or immutable
// ms.split(); // also can't borrow ms
*x += 100;
*y += 5000;
println!("split: {} {}", x, y); // split: 102 5000
} // custom drop occurs here
println!("{:?}", c); // Count { val: 5102 }
}
playground:
I don't think a reference to a temporary value like yours can be made to work in today's Rust.
If it's any help, if you specifically want to call a function with two &mut i32 parameters like you mentioned in the comments, e.g.
fn foo(a: &mut i32, b: &mut i32) {
*a += 1;
*b += 2;
println!("split: {} {}", a, b);
}
you can already do that with the same number of lines as you'd have if your chaining worked.
With the chaining, you'd call
let (x, y) = c.make_split().split();
foo(x, y);
And if you just leave out the conversion to a tuple, it looks like this:
let mut ms = c.make_split();
foo(&mut ms.top.val, &mut ms.second);
You can make it a little prettier by e.g. storing the mutable reference to val directly in CountSplit as first, so that it becomes foo(&mut ms.first, &mut ms.second);. If you want it to feel even more like a tuple, I think you can use DerefMut to be able to write foo(&mut ms.0, &mut ms.1);.
Alternatively, you can of course formulate this as a function taking a function
impl Count {
fn as_split<F: FnMut(&mut i32, &mut i32)>(&mut self, mut f: F) {
let mut second = 0;
f(&mut self.val, &mut second);
self.val += second;
}
}
and then just call
c.as_split(foo);

Is it possible to create a wrapper around an &mut that acts like an &mut

The following code fails to compile because MutRef is not Copy. It can not be made copy because &'a mut i32 is not Copy. Is there any way give MutRef similar semantics to &'a mut i32?
The motivation for this is being able to package up a large set of function parameters into a struct so that they can be passed as a group instead of needing to be passed individually.
struct MutRef<'a> {
v: &'a mut i32
}
fn wrapper_use(s: MutRef) {
}
fn raw_use(s: &mut i32) {
}
fn raw_ref() {
let mut s: i32 = 9;
let q = &mut s;
raw_use(q);
raw_use(q);
}
fn wrapper() {
let mut s: i32 = 9;
let q = MutRef{ v: &mut s };
wrapper_use(q);
wrapper_use(q);
}
No.
The name for this feature is "implicit reborrowing" and it happens when you pass a &mut reference where the compiler expects a &mut reference of a possibly different lifetime. The compiler only implicitly reborrows when the actual type and the expected type are both &mut references. It does not work with generic arguments or structs that contain &mut references. There is no way in current Rust to make a custom type that can be implicitly reborrowed. There is an open issue about this limitation dating from 2015, but so far nobody has proposed any way to lift it.
You can always implement your own method to explicitly reborrow:
impl<'a> MutRef<'a> {
// equivalent to fn reborrow(&mut self) -> MutRef<'_>
fn reborrow<'b>(&'b mut self) -> MutRef<'b> {
MutRef {v: self.v}
}
}
fn wrapper() {
let mut s: i32 = 9;
let mut q = MutRef{ v: &mut s };
wrapper_use(q.reborrow()); // does not move q
wrapper_use(q); // moves q
}
See also
Why is the mutable reference not moved here?
Type inference and borrowing vs ownership transfer

Rust error E0495 using split_at_mut in a closure

I'm encountering an "error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements" with this simple function:
fn assign_split_at_mut<'a, 'b, T>(s: &'b mut &'a mut [T], mid: usize) -> &'a mut [T] {
let (x, y) = (*s: &'a mut [T]).split_at_mut(mid);
*s = y;
x
}
I wrote a playpen example including this unsafe variant of split_at_mut that does work.
fn assign_split_at_mut_unsafe<'a, T>(s: &mut &'a mut [T], mid: usize) -> &'a mut [T] {
let len = (*s: &'a mut [T]).len();
let ptr = (*s: &'a mut [T]).as_mut_ptr();
unsafe {
use std::slice::from_raw_parts_mut;
assert!(mid <= len);
*s: &'a mut [T] = from_raw_parts_mut(ptr.offset(mid as isize), len - mid);
from_raw_parts_mut(ptr, mid)
}
}
In fact, I want to write roughly this:
pub fn slice_header<'a>(&'static self, mut header: &'a mut [u8])
-> MyResult<HeaderRefs<'a>>
{
// ...
let take = |l: usize| -> &'a mut [u8] {
let (x,y) = header.split_at_mut(l);
header = y; x
};
let hr = HeaderRefs {
params: self,
alpha: array_mut_ref![take(32),0,32],
gamma: array_mut_ref![take(16),32,16],
beta: take(self.beta_length as usize),
surb_log: take(self.surblog_length as usize),
surb: take(self.surb_length()),
};
// ...
Ok(hr)
}
I believe it would work fine if I simply wrote out a bunch of
let (alpha,header) = header.split_at_mut(32);
let (gamma,header) = header.split_at_mut(16);
// ...
Maybe it'd work if I put them into an array. I cannot get it to work with a closure, which would look much cleaner.
This is a borrowing issue:
fn assign_split_at_mut<'a, 'b, T>(s: &'b mut &'a mut [T], mid: usize) -> &'a mut [T] {
let (x, y) = (*s: &'a mut [T]).split_at_mut(mid);
*s = y;
x
}
Specifically, split_at_mut borrows s, so you cannot also assign to s while it is borrowed.
To understand the issue, imagine that we were talking about vectors here, with s: &mut Vec<T>: you could first borrow a slice from the Vec and then use s to mutate it.
This is why Rust specifies that the whole access path is borrowed, not just the leaf.
Okay, so what now?
As mentioned by #nox, the solution is to "dance":
move the ownership of &'a mut [T] out of s to a local variable
borrow this local variable
assign to s
This way, the borrow checker is appeased since it knows that modifying s cannot affect the local variable and its borrows.
There are various ways to move the ownership out of &mut X depending on the situation, some common ways are:
std::mem::replace,
std::mem::swap,
Option::take if X is an Option,
...
In your case, replace is the simpler. And the solution provided by #nox is rather simple:
fn reserve<'heap, T>(heap: &mut &'heap mut [T], len: usize) -> &'heap mut [T] {
let tmp: &'heap mut [T] = ::std::mem::replace(&mut *heap, &mut []);
let (reserved, tmp) = tmp.split_at_mut(len);
*heap = tmp;
reserved
}
An IRC user nox provided a clean answer by using mem::replace to move the &mut [T] that needs mutation out of the way first :
fn reserve<'heap, T>(heap: &mut &'heap mut [T], len: usize) -> &'heap mut [T] {
let tmp: &'heap mut [T] = ::std::mem::replace(&mut *heap, &mut []);
let (reserved, tmp) = tmp.split_at_mut(len);
*heap = tmp;
reserved
}

Resources