Hi, and sorry for the messy title ; I couldn't find a better way to introduce my problem.
I'm trying to implement a Defer3
trait, which is supposed to add a listen
method to any function with the following signature:
struct Instance;
struct Ret;
for<'a> fn(&'a mut Instance, P1, P2, P3) -> impl Future<Output = Ret> + 'a;
The idea is that the listen
method spawns an asynchronous task which handles deferred calls to the function, triggered by channel messages.
Here is the trait:
use async_lock::RwLock;
use async_channel::Sender;
trait Defer3<T, P1, P2, P3> {
fn listen(&self, instance: RwLock<T>) -> Sender<(P1, P2, P3)>;
}
and here's how I'm trying to implement it for that kind of function:
use core::future::Future;
impl<'a, T: 'static, F, P1, P2, P3, R> Defer3<T, P1, P2, P3> for F
where
F: Fn(&'a mut T, P1, P2, P3) -> R,
R: Future<Output = Ret> + 'a
{
fn listen(&self, instance: RwLock<T>) -> Sender<(P1, P2, P3)> {
let (tx, rx) = async_channel::unbounded();
let _task = async move {
while let Ok((p1, p2, p3)) = rx.recv().await {
let mut locked = instance.write().await;
let future = self(&mut *locked, p1, p2, p3);
let _ret = future.await;
}
};
tx
}
}
Now, I'm lost regarding the compiler's messages:
error[E0207]: the type parameter `R` is not constrained by the impl trait, self type, or predicates
--> crates/utils/src/lib.rs:54:41
|
54 | impl<'a, T: 'static, F, P1, P2, P3, R> Defer3<T, P1, P2, P3> for F
| ^ unconstrained type parameter
error[E0597]: `instance` does not live long enough
--> crates/utils/src/lib.rs:66:38
|
54 | impl<'a, T: 'static, F, P1, P2, P3, R> Defer3<T, P1, P2, P3> for F
| -- lifetime `'a` defined here
...
61 | fn listen(&self, instance: RwLock<T>) -> Sender<(P1, P2, P3)> {
| -------- binding `instance` declared here
...
66 | let mut locked = instance.write().await;
| ^^^^^^^^ borrowed value does not live long enough
67 | let future = self(&mut *locked, p1, p2, p3);
| ------------------------------ argument requires that `instance` is borrowed for `'a`
...
70 | };
| - `instance` dropped here while still borrowed
error[E0597]: `locked` does not live long enough
--> crates/utils/src/lib.rs:67:45
|
54 | impl<'a, T: 'static, F, P1, P2, P3, R> Defer3<T, P1, P2, P3> for F
| -- lifetime `'a` defined here
...
66 | let mut locked = instance.write().await;
| ---------- binding `locked` declared here
67 | let future = self(&mut *locked, p1, p2, p3);
| -----------^^^^^^-------------
| | |
| | borrowed value does not live long enough
| argument requires that `locked` is borrowed for `'a`
68 | let _ret = future.await;
69 | }
| - `locked` dropped here while still borrowed
-
why does the compiler tell me that
R
is unconstrained? It should be the return type of theSelf
function type. -
Once the future is used (after
let _ret = future.await
),locked
shouldn't be borrowed anymore. I don't understand whylocked
is still borrowed when it must be dropped.
Here is a sample function for reference:
fn demo_fn<'a>(_this: &'a mut Instance, _p1: u8, _p2: u8, _p3: u8) -> impl Future<Output = Ret> + 'a {
async {
// in a more realistic scenario, _this is used here,
// hence the lifetime binding on the return type.
Ret
}
}
Thank you!