Reputation: 13
I'm new to rust , I write some async code to send two request concurrently:
use std::time::Duration;
use futures::future::join_all;
use tokio::time::sleep;
// #[derive(Clone, Debug)]
pub struct Request {}
impl Request {
pub async fn do_req(&self , num : i32) -> i32 {
sleep(Duration::from_secs(1)).await;
num * 2
}
}
#[tokio::test]
async fn test() {
let v = vec![Request{} , Request{}];
let futs : Vec<_> = v.into_iter().map(|req|{
req.do_req(1)
}).collect();
let res = join_all(futs).await;
println!("{:?}", res);
}
but I get a error in the iterator "cannot return value referencing function parameter req
returns a value referencing data owned by the current function" in the line "req.do_req(1)".
I consider req.do_req(1) return a new value so I can't understand why the error arise, it's very kind if someone can tell me how it is happened and how to fix it,thank you.
Upvotes: 1
Views: 765
Reputation: 13750
The error message could be a bit more helpful. The fundamental issue is that you're trying to hold references to the elements of v
— the req
s — but those elements don't exist anymore because you've consumed v
(and therefore its elements) by calling v.into_iter()
. What the compiler is trying to say is that in v.into_iter().map(|req| ...)
, req
is an owned Request
, but the Future
s you're producing and collecting into futs
hold references to that owned data. When map
’s closure ends, req
is dropped (because it's owned, because of into_iter()
), and then those Future
s would be holding dangling references, which the compiler rightly prevents.
If you replace this with v.iter()
, it will work because the Future
s you've collected now hold references to data that still exists; nothing has been consumed.
Upvotes: 2