Desugared recursive async method - rust

I'm trying to write desugared recursive async method. Here is my attempt:
use std::future::*;
use std::pin::*;
struct TestRecursiveAsync;
impl TestRecursiveAsync {
pub fn foo(&self, value: u32) -> Pin<Box<(dyn Future<Output = u32>)>> {
let v: Pin<Box<(dyn Future<Output = u32> + 'static)>> = Box::pin(async move {
if value > 0 {
self.foo(value - 100).await
} else {
value
}
});
v
}
}
The compiler complains with this message (Playground):
Compiling playground v0.0.1 (/playground)
error[E0759]: cannot infer an appropriate lifetime
--> src/lib.rs:8:85
|
7 | pub fn foo(&self, value: u32) -> Pin<Box<(dyn Future<Output = u32>)>> {
| ----- this data with an anonymous lifetime `'_`...
8 | let v: Pin<Box<(dyn Future<Output = u32> + 'static)>> = Box::pin(async move {
| _____________________________________________________________________________________^
9 | | if value > 0 {
10 | | self.foo(value - 100).await
11 | | } else {
12 | | value
13 | | }
14 | | });
| |_________^ ...is captured here, requiring it to live as long as `'static`
|
help: to declare that the trait object captures data from argument `self`, you can add an explicit `'_` lifetime bound
|
7 | pub fn foo(&self, value: u32) -> Pin<Box<(dyn Future<Output = u32> + '_)>> {
| ^^^^
So the compiler requires &self to have 'static lifetime, but it has an anonymous. Is there a way to fix that?

Related

Conflicting lifetimes inside closure

I'm trying to create a trait for a Decoder that can return a packet that contains a reference inside. That is, I don't need to copy the packet to an owned object just so it's 'static.
Here's the sketch:
use std::sync::{Arc, Mutex};
pub trait DecodedPacket<'a>: Send {}
pub type OnConsume = Arc<dyn for<'a> Fn(&'a mut Option<Box<dyn DecodedPacket<'a>>>) + Send + Sync>;
pub trait Decoder: Send{
fn receive_ref(&self,on_packet: Arc<dyn for<'a> FnMut(Box<dyn DecodedPacket<'a>>)>);
}
pub struct DummyDecoder {}
impl Decoder for DummyDecoder {
fn receive_ref(&self,_: Arc<dyn for<'a> FnMut(Box<dyn DecodedPacket<'a>>)>){
unimplemented!();
}
}
struct DummyRenderer {
on_consume: OnConsume
}
impl DummyRenderer {
pub fn render(&self) {
let mut decoded_packet: Option<Box<dyn DecodedPacket<'_>>> = None;
let packet = (self.on_consume)(&mut decoded_packet);
//Render packet somehow here
}
}
fn main() {
let decoder: Box<dyn Decoder + Sync> = Box::new(DummyDecoder{});
let renderer_on_consume: OnConsume =
Arc::new(move |p: &mut Option<Box<dyn DecodedPacket>>| {
let decoded_packet: Arc<Mutex<Option<Box<dyn DecodedPacket>>>> =
Arc::new(Mutex::new(None));
let on_packet = Arc::new(move |packet: Box<dyn DecodedPacket>|{
decoded_packet.lock().unwrap().replace(packet);
});
decoder.receive_ref(on_packet);
if let Some(packet) = *decoded_packet.lock().unwrap() {
p.replace(packet);
}
});
let dummy_renderer = DummyRenderer{
on_consume: renderer_on_consume
};
dummy_renderer.render();
}
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=89a181ae763d220199be91c9cb552e80
You can see that receive_ref expects a function that can deal with all lifetimes, so it should work for a small non 'static lifetime. However, the compiler is making all the lifetimes 'static:
Error:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src/main.rs:35:58
|
35 | let decoded_packet: Arc<Mutex<Option<Box<dyn DecodedPacket>>>> =
| ^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 34:18...
--> src/main.rs:34:18
|
34 | Arc::new(move |p: &mut Option<Box<dyn DecodedPacket>>| {
| __________________^
35 | | let decoded_packet: Arc<Mutex<Option<Box<dyn DecodedPacket>>>> =
36 | | Arc::new(Mutex::new(None));
37 | | let on_packet = Arc::new(move |packet: Box<dyn DecodedPacket>|{
... |
43 | | }
44 | | });
| |_________^
note: ...but the lifetime must also be valid for the anonymous lifetime #1 defined on the body at 37:38...
--> src/main.rs:37:38
|
37 | let on_packet = Arc::new(move |packet: Box<dyn DecodedPacket>|{
| ______________________________________^
38 | | decoded_packet.lock().unwrap().replace(packet);
39 | | });
| |_____________^
note: ...so that the types are compatible
--> src/main.rs:42:27
|
42 | p.replace(packet);
| ^^^^^^
= note: expected `dyn DecodedPacket<'_>`
found `dyn DecodedPacket<'_>`
ps: I don't like the let decoded_packet: Arc<Mutex<Option<Box<dyn DecodedPacket>>>> = Arc::new(Mutex::new(None)); but I had to do it otherwise decoded_packet was getting borrowed by the closure and thus forcing the closure lifetime to be 'static

How can I write a boxed closure which mutates a reference to a struct?

I have some code that looks like this:
type Callback<T> = Box<Fn(&T) -> ()>;
struct Foo {
name: String,
}
impl Foo {
fn name_updater(&mut self) -> Callback<String> {
Box::new(|new_name| {
self.name = *new_name;
})
}
}
This code doesn't compile because the closure requires the static lifetime. However I'm unsure if this will resolve the question and because there aren't explicit lifetimes, it's not immediately clear to me what I'd need to do to resolve that.
Here is an example of the compilation error:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/lib.rs:9:9
|
9 | / Box::new(|new_name| {
10 | | self.name = *new_name;
11 | | })
| |__________^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 8:5...
--> src/lib.rs:8:5
|
8 | / fn name_updater(&mut self) -> Callback<String> {
9 | | Box::new(|new_name| {
10 | | self.name = *new_name;
11 | | })
12 | | }
| |_____^
note: ...so that the type `[closure#src/lib.rs:9:18: 11:10 self:&mut &mut Foo]` will meet its required lifetime bounds
--> src/lib.rs:9:9
|
9 | / Box::new(|new_name| {
10 | | self.name = *new_name;
11 | | })
| |__________^
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the expression is assignable:
expected std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r std::string::String) + 'static)>
found std::boxed::Box<dyn for<'r> std::ops::Fn(&'r std::string::String)>
How can I write a closure that is capable of mutating the struct's name property?
You need to bound a lifetime to your closure because you borrow something aka &mut self:
type Callback<'a, T> = Box<dyn FnMut(&T) -> () + 'a>;
#[derive(Debug)]
struct Foo {
name: String,
}
impl Foo {
fn name_updater(&mut self) -> Callback<str> {
Box::new(move |new_name| {
self.name.replace_range(.., new_name);
})
}
}
fn main() {
let mut foo = Foo {
name: String::from("foo"),
};
foo.name_updater()("bar");
println!("{:?}", foo);
}
Also note that you don't need to use a box:
#[derive(Debug)]
struct Foo {
name: String,
}
impl Foo {
fn name_updater<'a>(&'a mut self) -> impl FnMut(&str) -> () + 'a {
move |new_name| {
self.name.replace_range(.., new_name);
}
}
}
fn main() {
let mut foo = Foo {
name: String::from("foo"),
};
foo.name_updater()("bar");
println!("{:?}", foo);
}

Cannot infer an appropriate lifetime due to conflicting requirements in a recursive struct

When I try to compile this code:
pub struct Context<'a> {
pub outer: Option<&'a mut Context<'a>>,
}
impl<'a> Context<'a> {
pub fn inside(outer: &'a mut Context) -> Context<'a> {
Context { outer: Some(outer) }
}
}
I'm getting this error:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src/main.rs:7:9
|
7 | Context { outer: Some(outer) }
| ^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 5:1...
--> src/main.rs:5:1
|
5 | / impl<'a> Context<'a> {
6 | | pub fn inside(outer: &'a mut Context) -> Context<'a> {
7 | | Context { outer: Some(outer) }
8 | | }
9 | | }
| |_^
note: ...so that expression is assignable (expected Context<'a>, found Context<'_>)
--> src/main.rs:7:9
|
7 | Context { outer: Some(outer) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the method body at 6:5...
--> src/main.rs:6:5
|
6 | / pub fn inside(outer: &'a mut Context) -> Context<'a> {
7 | | Context { outer: Some(outer) }
8 | | }
| |_____^
note: ...so that expression is assignable (expected &mut Context<'_>, found &mut Context<'_>)
--> src/main.rs:7:31
|
7 | Context { outer: Some(outer) }
| ^^^^^
Why this is happening?
This is because you haven't met the obligations that you require.
Due to lifetime elision, your code is equivalent to:
pub fn inside<'b>(outer: &'a mut Context<'b>) -> Context<'a>
Change your code to
pub fn inside(outer: &'a mut Context<'a>) -> Context<'a>
And it will compile.

the lifetime 'a as defined on the body does not necessarily outlive the anonymous lifetime #1 defined on the body

I'm trying to create a function (f1) that adds an element to an array.
Here is my Rust code:
use std::mem;
struct T1<'a> {
value: &'a str,
}
fn main() {
let mut data: [T1; 1] = unsafe { mem::uninitialized() };
f1("Hello", &mut data[..]);
}
fn f1<'b, 'a: 'b>(s: &'a str, data: &'b mut[T1]) {
data[0] = T1::<'a> { value: s };
}
I get this error message:
error[E0308]: mismatched types
--> <anon>:13:15
|
13 | data[0] = T1::<'a> { value: s };
| ^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected type `T1<'_>`
= note: found type `T1<'a>`
note: the lifetime 'a as defined on the body at 12:49...
--> <anon>:12:50
|
12 | fn f1<'b, 'a: 'b>(s: &'a str, data: &'b mut[T1]) {
| __________________________________________________^ starting here...
13 | | data[0] = T1::<'a> { value: s };
14 | | }
| |_^ ...ending here
note: ...does not necessarily outlive the anonymous lifetime #1 defined on the body at 12:49
--> <anon>:12:50
|
12 | fn f1<'b, 'a: 'b>(s: &'a str, data: &'b mut[T1]) {
| __________________________________________________^ starting here...
13 | | data[0] = T1::<'a> { value: s };
14 | | }
| |_^ ...ending here
help: consider using an explicit lifetime parameter as shown: fn f1<'b, 'a:'b>(s: &'a str, data: &'b mut [T1<'a>])
--> <anon>:12:1
|
12 | fn f1<'b, 'a: 'b>(s: &'a str, data: &'b mut[T1]) {
| _^ starting here...
13 | | data[0] = T1::<'a> { value: s };
14 | | }
| |_^ ...ending here
Is there a way to write f1 that does what I'm trying to do?
You need to specify lifetime to the slice parameter:
fn f1<'b, 'a: 'b>(s: &'a str, data: &'b mut [T1<'a>]) {
data[0] = T1::<'a> { value: s };
}

Cannot infer appropriate lifetime for autoref when calling a method from an Iterator implementation

I am trying to implement the Iterator trait for a struct which acts as a borrower of an array of i32 values, but I keep running into the compiler complaining about not being able to infer a lifetime inside the next method.
I am aware of Need help understanding Iterator lifetimes, but since my struct just borrows a slice of the array anyway, I keep the memory of the actual elements separate from my IntegerArrayBag.
#[derive(Debug)]
struct IntegerArrayBag<'a> {
arr: &'a [i32],
idx: usize,
}
impl<'a> IntegerArrayBag<'a> {
fn len(&self) -> usize {
self.arr.len()
}
fn get(&self, idx: usize) -> Option<&i32> {
if self.arr.len() > idx {
Some(&self.arr[idx])
} else {
None
}
}
}
impl<'a> Iterator for IntegerArrayBag<'a> {
type Item = &'a i32;
fn next(&mut self) -> Option<&'a i32> {
let idx = self.idx;
self.idx += 1;
self.get(idx)
}
}
If I try to compile this code, the compiler complains with:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:27:14
|
27 | self.get(idx)
| ^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 24:5...
--> src/main.rs:24:5
|
24 | / fn next(&mut self) -> Option<&'a i32> {
25 | | let idx = self.idx;
26 | | self.idx += 1;
27 | | self.get(idx)
28 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:27:9
|
27 | self.get(idx)
| ^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 21:1...
--> src/main.rs:21:1
|
21 | / impl<'a> Iterator for IntegerArrayBag<'a> {
22 | | type Item = &'a i32;
23 | |
24 | | fn next(&mut self) -> Option<&'a i32> {
... |
28 | | }
29 | | }
| |_^
note: ...so that expression is assignable (expected std::option::Option<&'a i32>, found std::option::Option<&i32>)
--> src/main.rs:27:9
|
27 | self.get(idx)
| ^^^^^^^^^^^^^
You need to update your get method to return a reference with longer life:
// Use 'a from impl<'a> IntegerArrayBag<'a>
fn get(&self, idx: usize) -> Option<&'a i32> {
and then it will compile.
Changing get(…) to return Option<&'a i32> makes it compile.
Playground URL: https://play.rust-lang.org/?gist=10783e90287b7111c126&version=stable
Gist URL: https://gist.github.com/10783e90287b7111c126

Resources