Using reference lifetimes correctly in iterator - rust

I am trying to make an iterator out of some struct, s1, that has references within it with some lifetimes, say 'a and 'b. The iterator elements are new instances of the same struct type holding the same references. When I try to do this, the iterator elements appear to become subject to the lifetime of s1 instead of just 'a and 'b.
An example for clarity:
#[derive(Debug)]
pub struct MyStruct<'a, 'b> {
num: i32,
ref1: &'a i32,
ref2: &'b i32,
}
impl<'a, 'b> MyStruct<'a, 'b> {
pub fn with_next_nums(&self, n: i32) -> impl Iterator<Item=MyStruct> {
(1..=n).map(|i| MyStruct { num: self.num + i, ref1: self.ref1, ref2: self.ref2 })
}
}
fn main() {
let i1 = 1;
let i2 = 2;
let s1 = MyStruct{ num: 0, ref1: &i1, ref2: &i2 };
let s_next: Vec<_> = s1.with_next_nums(3).collect();
drop(s1); // commenting this line the program compiles
println!("{:?}", s_next);
}
The error I get is:
error[E0505]: cannot move out of `s1` because it is borrowed
--> src/main.rs:19:10
|
18 | let s_next: Vec<_> = s1.with_next_nums(3).collect();
| -------------------- borrow of `s1` occurs here
19 | drop(s1); // commenting this line the program compiles
| ^^ move out of `s1` occurs here
20 | println!("{:?}", s_next);
| ------ borrow later used here
For more information about this error, try `rustc --explain E0505`.
error: could not compile `playground` due to previous error
So, because I am dropping s1, Rust assumes the elements of s_next will become invalid, even though s_next only holds references to i1 and i2.
I suppose it is a matter of lifetime annotation, but I don't know how to fix it. If I were just producing a single struct out of s1, then I could annotate the return type like MyStruct<'a, 'b> and it would work, but just using impl Iterator<Item=MyStruct<'a, 'b>> as a return type does not solve it.

The problem with your version is that because of the lifetime elision rules, since you didn't specify the lifetimes for 'a and 'b in the returned MyStruct, the compiler assumes they have the same lifetime as self. So, this as if you wrote:
pub fn with_next_nums<'c>(&'c self, n: i32) -> impl Iterator<Item = MyStruct<'c, 'c>>
To fix that you need to explicitly declare the lifetimes as 'a and 'b:
pub fn with_next_nums(&self, n: i32) -> impl Iterator<Item = MyStruct<'a, 'b>>
Now there will be another error in the declaration of with_next_nums(), because it does borrow from self as the closure captures it. You can fix that by adding '_, as the compiler suggests, but then your iterator will borrow from self, so your code (that collects them into a Vec) will work, but similar code that does not collect() immediately will not:
fn main() {
let i1 = 1;
let i2 = 2;
let s1 = MyStruct {
num: 0,
ref1: &i1,
ref2: &i2,
};
// The iterator is still alive when we drop `s1`, but it borrows from it.
let s_next = s1.with_next_nums(3);
drop(s1);
let s_next: Vec<_> = s_next.collect();
println!("{:?}", s_next);
}
A better fix is to change the closure so it will only borrow the fields it needs and not self. You can do it like that:
pub fn with_next_nums(&self, n: i32) -> impl Iterator<Item = MyStruct<'a, 'b>> {
let MyStruct { num, ref1, ref2 } = *self;
(1..=n).map(move |i| MyStruct {
num: num + i,
ref1,
ref2,
})
}

The problem is that in this case you need to specify the lifetime of both the iterator elements and the iterator itself. If you just specify the lifetimes of the iterator elements (with impl Iterator<Item=MyStruct<'a, 'b>>), the compiler assumes you will deal with lifetimes by hand and will give up trying to automatically assign a lifetime to the iterator. However, it does need to have the lifetime of the struct, because it depends on it, so it will fail to compile. The compiler error will actually give you the fix in this case:
error[E0700]: hidden type for `impl Iterator<Item = MyStruct<'a, 'b>>` captures lifetime that does not appear in bounds
--> src/main.rs:10:9
|
9 | pub fn with_next_nums(&self, n: i32) -> impl Iterator<Item=MyStruct<'a, 'b>> {
| ----- hidden type `Map<RangeInclusive<i32>, [closure#src/main.rs:10:21: 10:24]>` captures the anonymous lifetime defined here
10 | (1..=n).map(|i| MyStruct { num: self.num + i, ref1: self.ref1, ref2: self.ref2 })
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: to declare that `impl Iterator<Item = MyStruct<'a, 'b>>` captures `'_`, you can add an explicit `'_` lifetime bound
|
9 | pub fn with_next_nums(&self, n: i32) -> impl Iterator<Item=MyStruct<'a, 'b>> + '_ {
| ++++
For more information about this error, try `rustc --explain E0700`.
error: could not compile `playground` due to previous error
So, you just need to also add that + '_ to the return type to solve the issue:
impl<'a, 'b> MyStruct<'a, 'b> {
pub fn with_next_nums(&self, n: i32) -> impl Iterator<Item=MyStruct<'a, 'b>> + '_ {
(1..=n).map(|i| MyStruct { num: self.num + i, ref1: self.ref1, ref2: self.ref2 })
}
}

Related

Mutable methods with lifetimes and later references

Consider the following code:
struct Foo<'a> {
borrowed: &'a u8,
owned_one: Vec<u8>,
owned_two: Vec<u8>,
output: usize
}
impl<'a> Foo<'a> {
fn do_stuff(&mut self) {
self.output = self.owned_one.len();
let zipped = self.owned_one.iter().zip(self.owned_two.iter());
Self::subroutine(&zipped);
}
fn subroutine<Arg: Iterator<Item=(&'a u8, &'a u8)>>(_zipped: &Arg) {}
}
fn main() {
let num = 0u8;
let mut foo = Foo {
borrowed: &num,
owned_one: vec![0],
owned_two: vec![1],
output: 0
};
foo.do_stuff();
let _out = &foo.output;
}
(playground link)
It doesn't compile, producing the following error:
error: lifetime may not live long enough
--> src/lib.rs:12:9
|
8 | impl<'a> Foo<'a> {
| -- lifetime `'a` defined here
9 | fn do_stuff(&mut self) {
| - let's call the lifetime of this reference `'1`
...
12 | Self::subroutine(&zipped);
| ^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'a`
I don't fully understand the complaint - surely self would always have the lifetime assigned to the class we're implementing? - but I can understand that both arguments to zip() need to last the same time. So I change do_stuff to take &'a mut self.
struct Foo<'a> {
borrowed: &'a u8,
owned_one: Vec<u8>,
owned_two: Vec<u8>,
output: usize
}
impl<'a> Foo<'a> {
fn do_stuff(&'a mut self) {
self.output = self.owned_one.len();
let zipped = self.owned_one.iter().zip(self.owned_two.iter());
Self::subroutine(&zipped);
}
fn subroutine<Arg: Iterator<Item=(&'a u8, &'a u8)>>(_zipped: &Arg) {}
}
fn main() {
let num = 0u8;
let mut foo = Foo {
borrowed: &num,
owned_one: vec![0],
owned_two: vec![1],
output: 0
};
foo.do_stuff();
let _out = &foo.output;
}
However, now compilation fails with:
error[E0502]: cannot borrow `foo.output` as immutable because it is also borrowed as mutable
--> src/lib.rs:27:16
|
26 | foo.do_stuff();
| -------------- mutable borrow occurs here
27 | let _out = &foo.output;
| ^^^^^^^^^^^
| |
| immutable borrow occurs here
| mutable borrow later used here
Why has specifying a lifetime for self in the argument list for do_stuff meant that I suddenly can't take the immutable reference to foo later; and what can I do about it?
writing fn do_stuff(&'a mut self) in this context mean that the lifetime of this borrow of self, must life as long as what this self has borrow borrowed. That very often not what you want.
Your mistake is here fn subroutine<Arg: Iterator<Item=(&'a u8, &'a u8)>>(_zipped: &Arg) {}. Think of lexical meaning of your declaration. Your method return nothing but require a "parent" lifetime ? There is no reason to. The simple solution is simply to introduce a new lifetime for your Item. Like fn subroutine<'i, Arg: Iterator<Item=(&'i u8, &'i u8)>>(_zipped: &Arg) {}. Unless your function return something link to 'a, no lifetime of parent should be here.
Also, it's better to accept IntoIterator it's more generic, and there is no reason to take it by reference and finally when you have such complex generic better use where, and really really if you want to be pedantic you need two lifetime:
fn subroutine<'i, 'j, Arg>(_zipped: Arg)
where
Arg: IntoIterator<Item = (&'i u8, &'j u8)>,
{
}

Trait object lifetime that matches a returning iterator's lifetime triggers a lifetime error

I have a trait with a function that returns Box<dyn Iterator<...>>. As I understand it, based off the definition, the lifetime of this returned iterator needs to match the trait object's. But in a function that drops both at the end, I get a lifetime error. Here's a minimal example, with assumptions added as comments:
trait Foo<'a> {
// The returned iterator's lifetime should match self's
fn bar(&'a self) -> Box<dyn Iterator<Item = usize> + 'a>;
}
struct FooImpl {
values: Vec<usize>
}
impl<'a> Foo<'a> for FooImpl {
fn bar(&'a self) -> Box<dyn Iterator<Item = usize> + 'a> {
Box::new(self.values.iter().cloned())
}
}
fn foo_bar_caller<'a>(foo: Box<dyn Foo<'a>>) {
// `foo` is moved into this fn
let _iter = foo.bar();
// `_iter` and `foo` should drop
}
fn main() {
let foo = FooImpl { values: vec![1, 2, 3, 4, 5] };
foo_bar_caller(Box::new(foo));
}
(rust playground with the code.) Running this gives the following lifetime error:
error[E0597]: `*foo` does not live long enough
--> src/main.rs:17:17
|
16 | fn foo_bar_caller<'a>(foo: Box<dyn Foo<'a>>) {
| -- lifetime `'a` defined here
17 | let _iter = foo.bar();
| ^^^^^^^^^
| |
| borrowed value does not live long enough
| argument requires that `*foo` is borrowed for `'a`
18 | // `_iter` and `foo` should drop
19 | }
| - `*foo` dropped here while still borrowed
For more information about this error, try `rustc --explain E0597`.
error: could not compile `playground` due to previous error
You probably meant to make the function Foo::bar generic over the reference lifetime, not the trait Foo:
trait Foo {
// The returned iterator's lifetime should match self's
fn bar<'a>(&'a self) -> Box<dyn Iterator<Item = usize> + 'a>;
}
By putting the lifetime on the trait Foo, you are unnecessarily (in this context, at least) restricting the lifetimes of the references you can use with a particular Foo::<'_>::bar implementation. A <T as Foo<'a>>::bar (T in the context of foo_bar_caller being Box<dyn Foo<'a>>) call can only take references with the lifetime 'a, but as #MaximilianBurszley points out in the comments, what you are actually passing to it is a temporary borrow that does not have the same lifetime 'a.
Playground
Note that you can make foo_bar_caller work with your existing code (with the trait Foo being generic over the lifetime) if you make the function take a reference with the same lifetime:
fn foo_bar_caller<'a>(foo: &'a dyn Foo<'a>) {
// `foo` is moved into this fn
let _iter = foo.bar();
// `_iter` and `foo` should drop
}
fn main() {
let foo = FooImpl { values: vec![1, 2, 3, 4, 5] };
foo_bar_caller(&foo);
}
Alternatively, you can use a higher-ranked trait bound (HRTB) to specify that foo_bar_caller must take in a value that implements Foo<'b> for all lifetimes 'b:
fn foo_bar_caller(foo: Box<dyn for<'b> Foo<'b>>) {
// `foo` is moved into this fn
let _iter = foo.bar();
// `_iter` and `foo` should drop
}
This allows the Foo<'_> implementation for the value foo to be valid for the lifetime for the temporary borrow created during the foo.bar() call (since it implements Foo<'_> for all lifetimes).
Playground for HRTB version

`cannot infer an appropriate lifetime for autoref due to conflicting requirements` but can't change anything due to trait definition constraints

I was implementing linked lists by following along too many linked lists. When trying to implement iter_mut(), I did it myself and made the following code:
type Link<T> = Option<Box<Node<T>>>;
pub struct List<T> {
head: Link<T>,
}
struct Node<T> {
elem: T,
next: Link<T>,
}
impl<T> List<T> {
pub fn iter_mut(&mut self) -> IterMut<T> {
IterMut::<T>(&mut self.head)
}
}
pub struct IterMut<'a, T>(&'a mut Link<T>);
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next<'b>(&'b mut self) -> Option<&'a mut T> {
self.0.as_mut().map(|node| {
self.0 = &mut (**node).next;
&mut (**node).elem
})
}
}
I am to avoiding coersions and elisions because being explicit lets me understand more.
Error:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/third.rs:24:16
|
24 | self.0.as_mut().map(|node| {
| ^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'b` as defined on the method body at 23:13...
--> src/third.rs:23:13
|
23 | fn next<'b>(&'b mut self) -> Option<&'a mut T> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/third.rs:24:9
|
24 | self.0.as_mut().map(|node| {
| ^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 20:6...
--> src/third.rs:20:6
|
20 | impl<'a, T> Iterator for IterMut<'a, T> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/third.rs:25:22
|
25 | self.0 = &mut (**node).next;
| ^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0495`.
I have looked at Cannot infer an appropriate lifetime for autoref due to conflicting requirements.
I understand a bit but not much. The problem that I am facing here is that if I try to change anything, an error pops saying that can't match the trait definition.
My thought was that basically I need to state somehow that lifetime 'b outlives 'a i.e <'b : 'a> but I can't figure out how to do it. Also, I have similar functions to implement iter() which works fine. It confuses me why iter_mut() produces such errors.
Iter
type Link<T> = Option<Box<Node<T>>>;
pub struct Iter<'a, T>(&'a Link<T>);
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
self.0.as_ref().map(|node| {
self.0 = &((**node).next);
&((**node).elem)
})
}
}
impl<T> List<T> {
pub fn iter(&self) -> Iter<T> {
Iter::<T>(&self.head)
}
}
☝️This works.
The key thing is that you need to be able to somehow extract an Option<&'a mut T> from a &'b mut IterMut<'a, T>.
To understand why IterMut<'a, T> := &'a mut Link<T> can't work, you need to understand what exactly you can do with a mutable reference. The answer, of course, is almost everything. You can copy data out of it, change its value, and lots of other things. The one thing you can't do is invalidate it. If you want to move the data under the mutable reference out, it has to be replaced with something of the same type (including lifetimes).
Inside the body of next, self is (essentially) &'b mut &'a mut Link<T>. Unless we know something about T (and we can't in this context), there's simply no way to produce something of type &'a mut Link<T> from this. For example, if this were possible in general, we'd be able to do
fn bad<'a, 'b, T>(_x: &'b mut &'a mut T) -> &'a mut T {
todo!()
}
fn do_stuff<'a>(x: &'a mut i32, y: &'a mut i32) {
// lots of stuff that only works if x and y don't alias
*x = 13;
*y = 42;
}
fn main() {
let mut x: &mut i32 = &mut 0;
let y: &mut i32 = {
let z: &mut &mut i32 = &mut x;
bad(z)
};
// `x` and `y` are aliasing mutable references
// and we can use both at once!
do_stuff(x, y);
}
(playground link)
The point is that if we were able to borrow something for a short (generic) lifetime 'b and return something that allowed modification during the longer lifetime 'a, we'd be able to use multiple short lifetimes (shorter than 'a and non-overlapping) to get multiple mutable references with the same lifetime 'a.
This also explains why the immutable version works. With immutable references, it's trivial to go from &'b &'a T to &'a T: just deference and copy the immutable reference. By contrast, mutable references don't implement Copy.
So if we can't produce a &'a mut Link<T> from a &'b mut &'a mut Link<T>, we certainly can't get an Option<&'a mut T out of it either (other than None). (Note that we can produce a &'b mut Link<T> and hence an Option<'b mut T>. That's what your code does right now.)
So what does work? Remember our goal is to be able to produce an Option<&'a mut T> from a &'b mut IterMut<'a, T>.
If we were able to produce a IterMut<'a, T> unconditionally, we'd be able to (temporarily) replace self with it and hence be able to directly access the IterMut<'a, T> associated to our list.
// This actually type-checks!
fn next<'b>(&'b mut self) -> Option<&'a mut T> {
let mut temp: IterMut<'a, T> = todo!(); // obviously this won't work
std::mem::swap(&mut self.0, &mut temp.0);
temp.0.as_mut().map(|node| {
self.0 = &mut node.next;
&mut node.elem
})
}
(playground link)
The easiest way to set things up so that this all works is by transposing IterMut<'a, T> a bit. Rather than having the mutable reference outside the option, make it inside! Now you'll always be able to produce an IterMut<'a, T> with None!
struct IterMut<'a, T>(Option<&mut Box<Node<T>>>);
Translating next, we get
fn next<'b>(&'b mut self) -> Option<&'a mut T> {
let mut temp: IterMut<'a, T> = IterMut(None);
std::mem::swap(&mut self.0, &mut temp.0);
temp.0.map(|node| {
self.0 = node.next.as_mut();
&mut node.elem
})
}
More idiomatically, we can use Option::take rather than std::mem::swap (This is mentioned earlier in Too Many Linked Lists).
fn next<'b>(&'b mut self) -> Option<&'a mut T> {
self.0.take().map(|node| {
self.0 = node.next.as_mut();
&mut node.elem
})
}
(playground link)
This actually ends up being slightly different than the implementation in Too Many Linked Lists. That implementation removes the double indirection of &mut Box<Node<T>> and replaces it with simply &mut Node<T>. However, I'm not sure how much you gain since that implementation still has a double deref in List::iter_mut and Iterator::next.
Rust is trying to say that you have a dangling reference.
self.0.as_mut() // value borrowed
self.0 = <> // underlying value changed here.
The problem is the following definition:
pub struct IterMut<'a, T>(&'a mut Link<T>)
This can't encapsulate that you will have a "empty" node meaning reached the end of the node.
Use the structure as mentioned in the book like:
pub struct IterMut<'a, T>(Option<&'a mut Node<T>>);
This ensures that you can leave None in its place when you run end of list and use take to modify the IterMut content behind the scenes.

How to write trait bound that supports += operation whose right hand is reference in complicated case in Rust [duplicate]

This question already has an answer here:
How to write a trait bound for adding two references of a generic type?
(1 answer)
Closed 2 years ago.
I'd like to write an Add operation supported Vector struct, and write a some trait that uses the Vector struct, so I wrote this.
use std::ops::*;
#[derive(Clone)]
struct Vector<T>(Vec<T>);
impl<'a, T> Add<&'a Vector<T>> for Vector<T>
where
T: AddAssign<&'a T>,
{
type Output = Vector<T>;
fn add(mut self, rhs: &'a Vector<T>) -> Self::Output {
self.0
.iter_mut()
.zip(rhs.0.iter())
.for_each(|(left, right)| {
*left += right;
});
self
}
}
trait SomeOperation<'a ,T>
where
T: AddAssign<&'a T>+Clone + 'a,
{
fn add(u:Vector<T>,v:&'a Vector<T>)->Vector<T>{
let w = u+v;
let x = v.clone()+&w;
x
}
}
But compilation error occurs.
21 | trait SomeOperation<'a ,T>
| -- lifetime `'a` defined here
...
27 | let x = v.clone()+&w;
| ^^
| |
| borrowed value does not live long enough
| requires that `w` is borrowed for `'a`
28 | x
29 | }
| - `w` dropped here while still borrowed
How can I avoid these types of error.
You talk about implementing AddAssign but your code tries to implement Add. Also, I couldn't figure out what SomeOperation was for. I added the Debug trait to the derive line.
use std::ops::*;
#[derive(Clone, Debug)]
struct Vector<T>(Vec<T>);
impl<'a, T> AddAssign<&'a Vector<T>> for Vector<T>
where
T: AddAssign<&'a T>
{
fn add_assign(&mut self, rhs: &'a Vector<T>) {
self.0
.iter_mut()
.zip(rhs.0.iter())
.for_each(|(left, right)| {
*left += right;
});
}
}
impl<'a, 'b, T> Add<& 'b Vector<T>> for & 'a Vector<T>
where
Vector<T>: AddAssign<& 'b Vector<T>>,
T: Clone,
{
type Output = Vector<T>;
fn add(self, other: & 'b Vector<T>) -> Self::Output {
let mut res: Vector<T> = self.clone();
res += other;
res
}
}
fn main() {
let mut v1: Vector<u32> = Vector(vec![1, 2, 3]);
let v2 = Vector(vec![4, 5, 6]);
println!("Add: {:?}", &v1 + &v2);
v1 += &v2;
println!("AddAssign{:?}", v1);
}

Cannot infer a lifetime for a struct containing a reference to a closure [duplicate]

This question already has answers here:
Lifetime annotation for closure argument
(2 answers)
How to declare a higher-ranked lifetime for a closure argument?
(3 answers)
Closed 5 years ago.
I am trying to make this simplified and self-contained version of my code compile:
struct FragMsgReceiver<'a, 'b: 'a> {
recv_dgram: &'a mut FnMut(&mut [u8]) -> Result<&'b mut [u8], ()>,
}
impl<'a, 'b> FragMsgReceiver<'a, 'b> {
fn new(
recv_dgram: &'a mut FnMut(&mut [u8])
-> Result<&'b mut [u8], ()>
) -> Self {
FragMsgReceiver { recv_dgram }
}
}
fn main() {
let recv_dgram = |buff: &mut [u8]| Ok(buff);
let fmr = FragMsgReceiver::new(&mut recv_dgram);
}
Here is the error:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:15:43
|
15 | let recv_dgram = |buff: &mut [u8]| Ok(buff);
| ^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 15:22...
--> src/main.rs:15:22
|
15 | let recv_dgram = |buff: &mut [u8]| Ok(buff);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that expression is assignable (expected &mut [u8], found &mut [u8])
--> src/main.rs:15:43
|
15 | let recv_dgram = |buff: &mut [u8]| Ok(buff);
| ^^^^
note: but, the lifetime must be valid for the block suffix following statement 1 at 16:53...
--> src/main.rs:16:53
|
16 | let fmr = FragMsgReceiver::new(&mut recv_dgram);
| _____________________________________________________^
17 | | }
| |_^
note: ...so that variable is valid at time of its declaration
--> src/main.rs:16:9
|
16 | let fmr = FragMsgReceiver::new(&mut recv_dgram);
| ^^^
From what I understand from the error message, the compiler doesn't understand that the buff reference (argument of recv_dgram) can actually live longer than the inner body of recv_dgram. I could be wrong though.
To give some context, I'm trying to create a struct that wraps a Rust Tokio UDP socket. To do this, I take a reference to a function recv_dgram. In my original code this function takes a buffer as argument, and returns a Future. When the Future is ready, the buffer will be filled. The Future's item also contains the address of sender and the amount of bytes that were written into the buffer.
Let's start by restoring elided lifetime in your declaration
struct FragMsgReceiver<'a, 'b: 'a> {
recv_dgram: &'a mut for<'c> FnMut(&'c mut [u8]) -> Result<&'b mut [u8], ()>,
}
This declaration means that FragMsgReceiver holds a mutable reference to a FnMut trait object which takes a mutable reference to a slice having any lifetime 'c and returns a reference with lifetime 'b: 'a.
This is not what you need. You need an FnMut which returns a reference with the same lifetime as the lifetime of the input parameter. This can be written as:
type FnTraitObject = FnMut(&mut [u8]) -> Result<&mut [u8], ()>;
struct FragMsgReceiver<'a> {
recv_dgram: &'a mut FnTraitObject,
}
impl<'a> FragMsgReceiver<'a> {
fn new(recv_dgram: &'a mut FnTraitObject) -> Self {
FragMsgReceiver { recv_dgram }
}
}
Lifetime elision does the right thing here, but the compiler still complains: "expected bound lifetime parameter, found concrete lifetime", pointing at FragMsgReceiver::new(&mut recv_dgram).
This error is caused by a limitation of Rust's type inference. We need to assist the inference by coercing the type of the closure as it was pointed out by DK.
fn constrain_handler<F>(f: F) -> F
where
F: FnMut(&mut [u8]) -> Result<&mut [u8], ()>,
{
f
}
// ...
let mut recv_dgram = constrain_handler(|buff| Ok(buff));
Complete code on the playground
To clarify, for<'c> means that 'c can be any lifetime and the lifetime is determined at a call site. For example, the pointer to the function fn foo(_: &u32) -> &u32 has the type for<'a> fn(&'a u32) -> &'a u32.

Resources