Proxy method for implementing Iterator, conflicting lifetime - rust

I'm trying to implement an iterator which simply proxies the next method to another method on the struct itself.
struct Element<'a>(&'a str);
struct IterStruct<'a> {
name: &'a str,
}
impl<'a> IterStruct<'a> {
fn name(&mut self) -> Option<Element> {
Some(Element(self.name))
}
}
impl<'a> Iterator for IterStruct<'a> {
type Item = Element<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.name()
}
}
I'm getting the conflicting requirements for lifetime error though:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/lib.rs:16:14
|
16 | self.name()
| ^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 15:5...
--> src/lib.rs:15:5
|
15 | / fn next(&mut self) -> Option<Self::Item> {
16 | | self.name()
17 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:16:9
|
16 | self.name()
| ^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 13:6...
--> src/lib.rs:13:6
|
13 | impl<'a> Iterator for IterStruct<'a> {
| ^^
= note: ...so that the types are compatible:
expected std::iter::Iterator
found std::iter::Iterator
Playground
How can I resolve this?

One solution is to specify that name outlives the IterStruct it is contained in:
struct Element<'a>(&'a str);
struct IterStruct<'a> {
name: &'a str,
}
impl<'a> IterStruct<'a> {
fn name<'s>(&'s mut self) -> Option<Element<'a>>
where
'a: 's, // <- specify that name outlives self
{
Some(Element(self.name))
}
}
impl<'a> Iterator for IterStruct<'a> {
type Item = Element<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.name()
}
}

Well you need to give borrow checker a way to infer the lifetimes. What's essentially missing is one of the following line
impl<'a> IterStruct<'a> {
fn name(&mut self) -> Option<Element> {
// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Some(Element(self.name))
}
}
into fn name(&mut self) -> Option<Element<'a>>. The Rust borrow checker will take care of the rest [Playground link].
Compiler seems smart enough to infer 'a should outlive 'self.

Related

Return reference wrapped in struct that requires lifetime parameters

How can I return a reference wrapped in a struct and what lifetime annotation is required? I am having a tough time formulating my exact question, but the following example illustrates what I am trying to do. I have a struct C that contains a reference to a struct B that requires lifetime parameters. I want a function on C that returns the reference to B wrapped in another struct Borrower that functions as an interface.
When compiling this I get an error when returning Borrower: 'cannot infer an appropriate lifetime for lifetime parameter 'b due to conflicting requirements'. How can I resolve this issue? What lifetime parameters can I enter? I feel like both 'a and 'b are not the right lifetimes.
Playground
struct C<'a, 'b> {
ref2: &'a mut B<'b>,
}
impl<'a, 'b> C<'a, 'b> {
fn get_borrower(&mut self) -> Borrower {
Borrower { ref3: self.ref2 }
}
}
struct Borrower<'a, 'b> {
ref3: &'a mut B<'b>,
}
impl<'a, 'b> Borrower<'a, 'b> {
fn print_and_add(&mut self) {
println!("ref is {}", self.ref3.ref1.i);
self.ref3.ref1.i += 1;
}
}
struct B<'a> {
ref1: &'a mut A,
}
struct A {
i: u32,
}
fn main() {
let mut a = A { i: 10 };
let mut b = B { ref1: &mut a };
let mut c = C { ref2: &mut b };
for _ in 0..10 {
let mut borrower = c.get_borrower();
borrower.print_and_add();
}
}
The issue is specifically in this method:
impl<'a, 'b> C<'a, 'b> {
fn get_borrower(&mut self) -> Borrower {
Borrower { ref3: self.ref2 }
}
}
We need to help the compiler understand which lifetime parameters are expected in the returned Borrower, because the inferred lifetimes here will be incorrect: The lifetime elision Borrower can be expanded to Borrower<'_, '_> where the anonymous lifetimes are both the lifetime of &mut self; If we call it 's, the equivalent signature would be:
fn get_borrower<'s>(&'s mut self) -> Borrower<'s, 's> {
This is clearly not right, because we know that the second lifetime is expected to be 'b, as directly described by field ref2 of type B<'b>. With the following signature (and after fixing unrelated errors), the code compiles successfully:
fn get_borrower(&mut self) -> Borrower<'_, 'b> {
The fun part is in the first parameter. One could be inclined to assume that we want it to be 'a instead of 's, but that would still lead to conflicting lifetimes:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src/main.rs:7:9
|
7 | Borrower { ref3: self.ref2 }
| ^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'s` as defined on the method body at 6:21...
--> src/main.rs:6:21
|
6 | fn get_borrower<'s>(&'s mut self) -> Borrower<'a, 'b> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:7:26
|
7 | Borrower { ref3: self.ref2 }
| ^^^^^^^^^
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, 'b> C<'a, 'b> {
| ^^
note: ...so that the expression is assignable
--> src/main.rs:7:9
|
7 | Borrower { ref3: self.ref2 }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `Borrower<'a, 'b>`
found `Borrower<'_, '_>`
This is because we are retrieving ref2 behind a mutable reference to self, and that one has its own lifetime. We cannot just move it out of self by force to fulfill the lifetime 'a, nor can we pass a &'s mut &'a mut B<'b> instead. Therefore, returning a Borrower<'s, 'b> is the right thing to do: as it is implicit that 'a: 's ('a outlives 's), the covariance in this lifetime will enable this method to narrow the mutable reference &'a mut B<'b> into its subtype &'s mut B<'b>.
----------
| 'a |
| ------ |
|| 's | ---> Borrower<'s, 'b>
|| | |
| ------ |
----------
See also:
mutably borrow fields from a mutably borrowed struct
How can this instance seemingly outlive its own parameter lifetime?

Lifetime for Cursor in Iteration

use std::io::Cursor;
use bytes::BytesMut;
struct Parser<'a> {
stream: &'a mut Cursor<&'a [u8]>
}
fn parse<'a>(buf:&'a mut Cursor<&'a [u8]>) -> Option<(usize, &'a str)> {
None
}
impl<'a> Iterator for Parser<'a> {
type Item = (usize, &'a str);
fn next(&mut self) -> Option<Self::Item> {
parse(self.stream)
}
}
fn main() {
let mut buf = BytesMut::with_capacity(1024);
let mut cursor = Cursor::new(&buf[..]);
let mut parser = Parser {stream: &mut cursor};
}
Playground link
Basically, I want to parse a buf without copy but failed to compile. Could anyone help? Much appreciated!
Error message:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in function call due to conflicting requirements
--> src/main.rs:15:9
|
15 | parse(self.stream)
| ^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 14:5...
--> src/main.rs:14:5
|
14 | fn next(&mut self) -> Option<Self::Item> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:15:15
|
15 | parse(self.stream)
| ^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 12:6...
--> src/main.rs:12:6
|
12 | impl<'a> Iterator for Parser<'a> {
| ^^
note: ...so that the expression is assignable
--> src/main.rs:15:15
|
15 | parse(self.stream)
| ^^^^^^^^^^^
= note: expected `&mut std::io::Cursor<&[u8]>`
found `&mut std::io::Cursor<&'a [u8]>`
You need a different lifetime for what is inside the cursor:
struct Parser<'a, 'b> {
stream: &'a mut Cursor<&'b [u8]>,
}
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=0c36650015dc7fb4d425794fca934242
The reason is to do with the fact that your stream is a mutable reference. If you make it immutable, everything works.
I could not explain why better than Ryan Levick did in his video he made on lifetimes.
That video should be one of the recommended learning materials 😃

Problem with lifetimes and implementing Clone

I'm trying to define a struct representing a function that can be composed using different arithmetic operations (only addition has been implemented).
I would like to implement Clone for my struct, however I can't seem to it to work:
use std::ops::Add;
use std::boxed::Box;
use std::clone::Clone;
type InputT = i32;
type OutputT = f64;
pub struct ComposableFn<'a> {
f: Box<dyn 'a + Fn(InputT) -> OutputT>,
}
impl<'a> ComposableFn<'a> {
pub fn new<F: 'a + Fn(InputT) -> OutputT>(f: F) -> Self {
Self {
f: Box::new(f)
}
}
pub fn compute(&self, x: InputT) -> OutputT {
(self.f)(x)
}
}
impl<'a> Add<&'a ComposableFn<'a>> for &'a ComposableFn<'a> {
type Output = ComposableFn<'a>;
fn add(self, rhs: &'a ComposableFn) -> Self::Output {
ComposableFn::new(move |x| self.compute(x) + rhs.compute(x))
}
}
impl<'a> Clone for ComposableFn<'a> {
fn clone(&'a self) -> Self {
ComposableFn::new(move |x| self.compute(x))
}
}
fn main() {
let id = ComposableFn::new(|x| x.into());
println!("{}", id.compute(12));
let double = &id + &id;
println!("{}", double.compute(7));
let triple = &double + &id;
println!("{}", triple.compute(3));
}
When compiling I get the following error:
error[E0308]: method not compatible with trait
--> src/main.rs:33:5
|
33 | fn clone(&'a self) -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected fn pointer `fn(&ComposableFn<'a>) -> ComposableFn<'_>`
found fn pointer `fn(&'a ComposableFn<'a>) -> ComposableFn<'_>`
note: the anonymous lifetime #1 defined on the method body at 33:5...
--> src/main.rs:33:5
|
33 | fn clone(&'a self) -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 32:6
--> src/main.rs:32:6
|
32 | impl<'a> Clone for ComposableFn<'a> {
| ^^
error: aborting due to previous error
Removing the 'a from fn clone(&'a self) results in the following error instead:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:34:27
|
34 | ComposableFn::new(move |x| self.compute(x))
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 33:5...
--> src/main.rs:33:5
|
33 | fn clone(&self) -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that the types are compatible
--> src/main.rs:34:27
|
34 | ComposableFn::new(move |x| self.compute(x))
| ^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `&ComposableFn<'_>`
found `&ComposableFn<'a>`
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 32:6...
--> src/main.rs:32:6
|
32 | impl<'a> Clone for ComposableFn<'a> {
| ^^
note: ...so that the expression is assignable
--> src/main.rs:34:9
|
34 | ComposableFn::new(move |x| self.compute(x))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `ComposableFn<'a>`
found `ComposableFn<'_>`
error: aborting due to previous error
Is there a way to fix this?
You cannot implement Clone this way. Clone requires the return type to match exactly, which means the exact same lifetime 'a. But you're trying to make a clone that references self which has a different lifetime.
The straightforward solution would be to just clone f. Unfortunately, you can't clone a Box<dyn...>, at least not without some help. See: How to clone a struct storing a boxed trait object?
The only direct solution would be to swap Box out with Rc so they share ownership:
use std::rc::Rc;
pub struct ComposableFn<'a> {
f: Rc<dyn 'a + Fn(InputT) -> OutputT>,
}
impl Clone for ComposableFn<'_> {
fn clone(&self) -> Self {
ComposableFn { f: self.f.clone() }
}
}

cannot infer an appropriate lifetime for lifetime parameter with multiple references with the same lifetime inside a struct [E0495]

I had gotten an error in my code about lifetime inferrence, and I have been able to reduce the code to the following:
use std::collections::HashMap;
struct A<'a> {
x: &'a mut HashMap<&'a str, i32>,
}
impl<'a> A<'a> {
fn new(x: &'a mut HashMap<&'a str, i32>) -> Self {
Self { x }
}
fn test(&mut self) {
let a = A::new(self.x);
}
}
fn main() {
}
The error that results from this is
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src/main.rs:13:17
|
13 | let a = A::new(self.x);
| ^^^^^^
|
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 test(&mut self) {
13 | | let a = A::new(self.x);
14 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:13:24
|
13 | let a = A::new(self.x);
| ^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 7:6...
--> src/main.rs:7:6
|
7 | impl<'a> A<'a> {
| ^^
note: ...so that the expression is assignable
--> src/main.rs:13:24
|
13 | let a = A::new(self.x);
| ^^^^^^
= note: expected `&mut std::collections::HashMap<&str, i32>`
found `&mut std::collections::HashMap<&'a str, i32>`
I do not understand what is the error in this case, but I did find that if I add a lifetime 'b to struct A, such that the str reference in the HashMap has a lifetime of 'b, the codes does compile. Here is how the code looks like after the aforementioned change:
use std::collections::HashMap;
struct A<'a, 'b> {
x: &'a mut HashMap<&'b str, i32>,
}
impl<'a, 'b> A<'a, 'b> {
fn new(x: &'a mut HashMap<&'b str, i32>) -> Self {
Self { x }
}
fn test(&mut self) {
let a = A::new(self.x);
}
}
fn main() {
}
However, I have no idea why that change works. To my understanding, having both lifetimes be 'a means that A must live as long as the HashMap, and the HashMap must live as long as the &strs that are used as its keys, which I see no issue with. I also do not see how the change adds any additional information for the compiler. Can anyone please shed some light for me on this situation?
Change the A::test() function into
fn test(&'a mut self) { // Add lifetime specification
let a = A::new(self.x);
}
and it should work.
The compiler said it cannot infer lifetime for A::new(), and the first note mentioned "anonymous lifetime", that means the compiler doesn't know the lifetime of self.x in A::new(self.x). So we just need to tell the compiler that self has a lifetime of 'a.

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

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

Resources