huntc
April 12, 2021, 5:36am
1
Hey there,
I'm trying to figure out a method for a trait I have that can return Tokio's Timeout
type having wrapped a channel recv
. I understand that async
closure types are anonymous and that this is obviously the root cause of my problems, so I assume I'm just going about things the wrong way.
Here's a sample with the problem:
trait SomeTrait {
fn my_func(&self) -> Timeout<Pin<Box<dyn Future<Output = Option<u32>>>>>;
}
impl SomeTrait for u32 {
fn my_func(&self) -> Timeout<Pin<Box<dyn Future<Output = Option<u32>>>>> {
let (tx, mut rx) = channel::<u32>(1);
let _ = tx.send(*self);
async {
timeout(Duration::from_millis(1000), rx.recv()).await
}
}
}
The problem reported is:
18 | / async {
19 | | timeout(Duration::from_millis(1000), rx.recv()).await
20 | | }
| |_________^ expected struct `tokio::time::Timeout`, found opaque type
|
= note: expected struct `tokio::time::Timeout<Pin<Box<(dyn Future<Output = Option<u32>> + 'static)>>>`
found opaque type `impl Future`
Code on Rust Playground .
Help most appreciated.
alice
April 12, 2021, 5:41am
2
The way you create a pinned boxed future is with Box::pin
, so given your return type, you would need to do this:
let inner = Box::pin(async move {
rx.recv().await
});
timeout(Duration::from_millis(1000), inner)
Though you would usually not mention the Timeout
type in a trait signature. If you don't do that, the return becomes:
Box::pin(async move {
timeout(Duration::from_millis(1000), rx.recv().await)
})
1 Like
huntc
April 12, 2021, 6:01am
3
Thank you so much for the blazingly fast and helpful reply!
I'm not quite getting:
Though you would usually not mention the Timeout type in a trait signature. If you don't do that, the return becomes...
Could I push you to provide the type signature in that instance? The timeout
function is going to want to return a Timeout
type, right?
My updated code in the playground .
alice
April 12, 2021, 6:04am
4
First you need to move the .await
a bit:
Box::pin(async move {
timeout(Duration::from_millis(1000), rx.recv()).await
})
Now all that is left is to fix the return type to:
Pin<Box<dyn Future<Output = Result<Option<u32>, Elapsed>>>>
or you can match on the timeout and do something sane if it times out.
1 Like
huntc
April 12, 2021, 6:10am
5
That's amazing - thank you so much. The code as a whole for anyone else reading this:
trait SomeTrait {
fn my_func(&self) -> Pin<Box<dyn Future<Output = Result<Option<u32>, Elapsed>>>>;
}
impl SomeTrait for u32 {
fn my_func(&self) -> Pin<Box<dyn Future<Output = Result<Option<u32>, Elapsed>>>> {
let (tx, mut rx) = channel::<u32>(1);
let _ = tx.send(*self);
Box::pin(async move {
timeout(Duration::from_millis(1000), rx.recv()).await
})
}
}
system
Closed
July 11, 2021, 6:11am
6
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.