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 😃
Related
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?
Here's a playground link that reproduces the error: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=86ec4f11f407f5d04a8653cc904f991b
I have a trait FooTraitMut that provides access to a specific range of data inside of BarStruct, and I want to generalize this trait so that it can access the same range on multiple BarStructs in lockstep. So I have a MutChannels trait that acts like a type-level function to produce the tuple of references that a visitor needs, e.g. (T, U) --> (&mut T, &mut U).
I haven't actually gotten to the point of using Channels2 because I can't get the simpler Channels1 case to work.
In the playground, the same is done for an immutable trait FooTraitRef, which works as intended. But the mutable one is broken due to an autoref lifetime issue. I think some kind of implicit transformation is happening to the lifetime of self, because I can inline the indexer function and it works fine.
Any help would be greatly appreciated.
The code in question:
struct BarStruct<T> {
data: [T; 1],
}
pub struct Channels1<T>(T);
pub struct Channels2<T, U>(T, U);
fn indexer(mut f: impl FnMut(usize)) {
f(0)
}
trait FooMutTrait {
type Data: for<'a> MutChannels<'a>;
fn foo<'a, F>(&'a mut self, f: F)
where
F: FnMut(<Self::Data as MutChannels<'a>>::Mut);
}
trait MutChannels<'a> {
type Mut;
}
impl<'a, T: 'a> MutChannels<'a> for Channels1<T> {
type Mut = &'a mut T;
}
impl<'a, T: 'a, U: 'a> MutChannels<'a> for Channels2<T, U> {
type Mut = (&'a mut T, &'a mut U);
}
impl<T> BarStruct<T> {
fn get_data_mut<'a>(&'a mut self, i: usize) -> &'a mut T {
&mut self.data[i]
}
}
impl<T> FooMutTrait for BarStruct<T>
where
T: 'static,
{
type Data = Channels1<T>;
#[inline]
fn foo<'a, F>(&'a mut self, mut f: F)
where
F: FnMut(<Self::Data as MutChannels<'a>>::Mut),
{
indexer(|i| f(self.get_data_mut(i)))
// This works.
// f(self.get_data_mut(0))
}
}
And the error:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/lib.rs:85:28
|
85 | indexer(|i| f(self.get_data_mut(i)))
| ^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'_` as defined on the body at 85:17...
--> src/lib.rs:85:17
|
85 | indexer(|i| f(self.get_data_mut(i)))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that closure can access `self`
--> src/lib.rs:85:23
|
85 | indexer(|i| f(self.get_data_mut(i)))
| ^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the method body at 81:12...
--> src/lib.rs:81:12
|
81 | fn foo<'a, F>(&'a mut self, mut f: F)
| ^^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:85:23
|
85 | indexer(|i| f(self.get_data_mut(i)))
| ^^^^^^^^^^^^^^^^^^^^
This error can be reproduced by this example:
fn indexer(mut f: impl FnMut()) {}
fn foo<'a, F>(a: &'a mut String, mut f: F)
where
F: FnMut(&'a mut str),
{
indexer(|| f(a.as_mut_str()));
}
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/lib.rs:7:20
|
7 | indexer(|| f(a.as_mut_str()));
| ^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'_` as defined on the body at 7:13...
--> src/lib.rs:7:13
|
7 | indexer(|| f(a.as_mut_str()));
| ^^^^^^^^^^^^^^^^^^^^
note: ...so that closure can access `a`
--> src/lib.rs:7:18
|
7 | indexer(|| f(a.as_mut_str()));
| ^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 3:8...
--> src/lib.rs:3:8
|
3 | fn foo<'a, F>(a: &'a mut String, mut f: F)
| ^^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:7:18
|
7 | indexer(|| f(a.as_mut_str()));
| ^^^^^^^^^^^^^^
What is happening is that F is typed to expect an 'a reference, but that's not what the closure can provide. The closure converts the &'a mut T into a shorter lifetime &'_ mut T. From my understanding, it would be unsound for FnMuts to preserve the outer lifetime since the function would be able to leak references outside its scope and could violate Rust's referential guarantees. This problem doesn't come up with immutable borrows since they are less restricted and the closure doesn't shorten their lifetime.
This can be fixed by allowing F to work for any lifetime:
fn indexer(mut f: impl FnMut()) {}
fn foo<'a, F>(a: &'a mut String, mut f: F)
where
F: FnMut(&mut str), // <--------
{
indexer(|| f(a.as_mut_str()));
}
Or using FnOnce since its functionality more constrained and doesn't require shortening the lifetimes:
fn indexer(f: impl FnOnce()) {} // <--------
fn foo<'a, F>(a: &'a mut String, mut f: F)
where
F: FnOnce(&'a mut str), // <--------
{
indexer(move || f(a.as_mut_str())); // added move so that the reference isn't reborrowed
}
The FnOnce change is trivial to apply to your case. However, relaxing F to work for any lifetime is met with errors about MutChannels<'_>::Mut not being the same as &'_ mut T, which I'm not sure how to handle.
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.
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?
}
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.