Vector of async functions that receives arguments passed by reference - rust

I want to create a vector of async functions, but it only works with the 'static lifetime:
use std::future::Future;
use std::pin::Pin;
type BoxFuture<T> = Pin<Box<dyn Future<Output = T>>>;
type SimpleHandler = Box<dyn Fn(&u32, &u64) -> BoxFuture<Option<String>>>;
#[tokio::main]
async fn main() -> std::io::Result<()> {
let v: Vec<SimpleHandler> = vec![
Box::new(|a, b| Box::pin(handle_create_group(a, b))),
Box::new(|a, b| Box::pin(handle_drop_group(a, b))),
];
for f in &v {
println!("{:?}", (f)(&0, &0).await);
}
Ok(())
}
async fn handle_create_group(a: &u32, b: &u64) -> Option<String> {
Some("hello".into())
}
async fn handle_drop_group(a: &u32, b: &u64) -> Option<String> {
Some("world".into())
}
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter '_ in function call due to conflicting requirements
--> src/main.rs:10:34
|
10 | Box::new(|a, b| Box::pin(handle_create_group(a, b))),
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 10:18...
--> src/main.rs:10:18
|
10 | Box::new(|a, b| Box::pin(handle_create_group(a, b))),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:10:54
|
10 | Box::new(|a, b| Box::pin(handle_create_group(a, b))),
| ^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the expression is assignable
--> src/main.rs:10:25
|
10 | Box::new(|a, b| Box::pin(handle_create_group(a, b))),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `std::pin::Pin<std::boxed::Box<(dyn std::future::Future<Output = std::option::Option<std::string::String>> + 'static)>>`
found `std::pin::Pin<std::boxed::Box<dyn std::future::Future<Output = std::option::Option<std::string::String>>>>`
Can I set the future's lifetime to be bound to the argument lifetime?

I found solution:
type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + 'a>>;
type SimpleHandler = Box<dyn for<'a> Fn(&'a u32, &'a u64) -> BoxFuture<'a, Option<String>>>;

Related

How to represent an opaque type in a struct field

I am using the genawaiter crate for generator functions to implement
single-threaded "multitasking".
I have this code to create a new Thread, and pass a generator to it, but I am struggling
to find how to represent the impl Future type that gen!() returns.
use genawaiter::rc::{gen, Gen};
use genawaiter::yield_;
struct Thread {
function: genawaiter::rc::Gen<(), Option<Sprite>, /*What can go here?*/>,
}
struct Sprite {/*fields here*/}
fn main() {
let thread1 = Thread {
function: gen!({
let object: Option<&mut Sprite> = yield_!(());
// do stuff with `object`
println!("Hi");
}),
};
}
The type that the gen!() macro returns is.
genawaiter::rc::Gen<(),Option<Sprite>,impl Future<Output = ()>>
If I try to set this as the type of the function field, I get this error message:
error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in path
--> src/main.rs:20:55
|
20 | function: genawaiter::rc::Gen<(), Option<Sprite>, impl Future<Output = ()>>,
| ^^^^^^^^^^^^^^^^^^^^^^^^
For more information about this error, try `rustc --explain E0562`.
error: could not compile `testing` due to previous error
struct EmptyFuture{}
impl Future for EmptyFuture {
type Output = ();
fn poll(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Self::Output> {
std::task::Poll::Ready(())
}
}
If I try putting this EmptyFuture struct in the function field, it also does
not work, and I get this error message:
error[E0308]: mismatched types
--> src/main.rs:27:19
|
27 | function: gen!({
| ___________________^____-
| |___________________|
| ||
28 | || let object: Option<Sprite> = yield_!(());
29 | || println!("Hi");
30 | || }),
| ||_________-^ expected struct `EmptyFuture`, found opaque type
| |_________|
| the found `async` block
|
::: /home/calvin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/mod.rs:72:43
|
72 | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
| ------------------------------- the found opaque type
|
= note: expected struct `genawaiter::rc::Gen<_, _, EmptyFuture>`
found struct `genawaiter::rc::Gen<_, _, impl Future<Output = ()>>`
= note: this error originates in the macro `gen` (in Nightly builds, run with -Z macro-backtrace for more info)
The only semi-relavant thing I could find on stackoverflow was this,
but that is about a function /returning/ an opaque type.
How can I represent the opaque type in my struct? Also, does it make a difference
whether it is an empty type (impl Future<Output = ()>) or some other struct(impl Future<Output = SomeStruct>)?
Edit:
I tried Box<dyn Future<Output = ()>>, and got this error:
error[E0277]: `(dyn Future<Output = ()> + 'static)` cannot be unpinned
--> src/target/mod.rs:325:15
|
325 | function: genawaiter::rc::Gen<(), Option<Sprite>, Box<dyn Future<Output = ()>>>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `(dyn Future<Output = ()> + 'static)`
|
= note: consider using `Box::pin`
= note: required because of the requirements on the impl of `Future` for `Box<(dyn Future<Output = ()> + 'static)>`
note: required by a bound in `genawaiter::rc::Gen`
--> /home/calvin/.cargo/registry/src/github.com-1ecc6299db9ec823/genawaiter-0.99.1/src/rc/generator.rs:11:25
|
11 | pub struct Gen<Y, R, F: Future> {
| ^^^^^^ required by this bound in `genawaiter::rc::Gen`
For more information about this error, try `rustc --explain E0277`.
I followed the compiler suggestion and changed it to
Pin<Box<dyn Future<Output = ()>>>, but now I am getting a
similar error as before:
error[E0308]: mismatched types
--> src/main.rs:28:19
|
28 | function: gen!({
| ___________________^____-
| |___________________|
| ||
29 | || let object: Option<Sprite> = yield_!(());
30 | || println!("Hi");
31 | || }),
| ||_________-^ expected struct `Pin`, found opaque type
| |_________|
| the found `async` block
|
::: /home/calvin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/mod.rs:72:43
|
72 | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
| ------------------------------- the found opaque type
|
= note: expected struct `genawaiter::rc::Gen<_, _, Pin<Box<(dyn Future<Output = ()> + 'static)>>>`
found struct `genawaiter::rc::Gen<_, _, impl Future<Output = ()>>`
= note: this error originates in the macro `gen` (in Nightly builds, run with -Z macro-backtrace for more info)
For more information about this error, try `rustc --explain E0308`.
You could try boxing trait object. That is use Box<dyn Future<Output = ()>>. This will cost you an allocation per created future, but it's the simplest solution. And practically the only one if you don't (or can't) name a type.

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

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() }
}
}

Desugared recursive async method

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?

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.

Resources