I tried this code:
async fn sum(idx: usize, num: u8) {
let sum = idx + num as usize;
println!("Sum = {}", sum);
}
async fn test() {
let results = futures::future::join_all(
(0..10).into_iter()
.enumerate()
.map(|(idx, num)| {
async {
sum(idx, num).await;
}
})
).await;
dbg!(results);
}
I expected to see this get compiled, but it gave me
error[E0373]: async block may outlive the current function, but it borrows `num`, which is owned by the current function
--> src/main.rs:146:17
|
146 | / async {
147 | | sum(idx, num).await;
| | --- `num` is borrowed here
148 | | }
| |_________________^ may outlive borrowed value `num`
|
note: async block is returned here
--> src/main.rs:146:17
|
146 | / async {
147 | | sum(idx, num).await;
148 | | }
| |_________________^
help: to force the async block to take ownership of `num` (and any other referenced variables), use the `move` keyword
|
146 | async move {
| ++++
The suggestion is plausible here, but in my actual code, I cannot easily add move because it also moves other values that I can only borrow and thus breaks my code.
The error makes sense in someway but I think rustc can easily copy num for me since it's just plain old data that is Copy.
I also tried other simple numeric types but they didn't work either.
Interestingly, rustc didn't raise an error for idx even when num is also usize, so I think the error is not self-consistent.
When searching issues, #127012 seems very similar to the code here, but I don't know whether they correlate.
Meta
rustc --version --verbose:
rustc 1.79.0 (129f3b996 2024-06-10)
binary: rustc
commit-hash: 129f3b9964af4d4a709d1383930ade12dfe7c081
commit-date: 2024-06-10
host: aarch64-apple-darwin
release: 1.79.0
LLVM version: 18.1.7
Updates
Update 0629: A more complete version that is closer to my actual code and cannot simply be resolved by adding move is
use std::time::Duration;
use tokio::time::sleep;
async fn sum(idx: usize, num: u8) -> usize {
// the code logic is a mock for actual computation and
// extracted from the closure to inform rustc
// that I need idx and num as values so that it should just copy them for me
idx + num as usize
}
async fn logging_mock(result: usize, id: usize) {
println!("Result={}, id = {}", result, id);
}
async fn mock_request(result: usize, request_string: String, request_configs: &str) -> Result<(), String> {
// request fn consumes `request_string` and `result` and references `request_configs`
dbg!("Requesting {} with {} and {}", result, request_string, request_configs);
Ok(())
}
#[derive(Debug)]
struct Configs {
request_template: String,
super_large_config: String,
some_other_data: String,
}
#[tokio::main]
async fn main() {
let mut configs = Configs {
request_template: "hello".to_string(),
super_large_config: "world".to_string(),
some_other_data: String::new(),
};
let results = futures::future::join_all(
(0..10).into_iter()
.enumerate()
.map(|(idx, num)| {
async {
let s = sum(idx, num).await;
// comment out the above line and simple mocks below make the code compiled
// let s = 1;
// let idx = 1;
let template = configs.request_template.clone();
mock_request(s, template, &configs.super_large_config).await.unwrap();
// non-emergent logging, prevents accidental DoS attack
sleep(Duration::from_millis(idx as u64)).await;
logging_mock(s, idx).await;
}
})
).await;
configs.some_other_data.push_str("do something to configs");
dbg!(configs);
dbg!(results);
}
I tried this code:
I expected to see this get compiled, but it gave me
The suggestion is plausible here, but in my actual code, I cannot easily add
movebecause it also moves other values that I can only borrow and thus breaks my code.The error makes sense in someway but I think rustc can easily copy
numfor me since it's just plain old data that isCopy.I also tried other simple numeric types but they didn't work either.
Interestingly, rustc didn't raise an error for
idxeven whennumis alsousize, so I think the error is not self-consistent.When searching issues, #127012 seems very similar to the code here, but I don't know whether they correlate.
Meta
rustc --version --verbose:Updates
Update 0629: A more complete version that is closer to my actual code and cannot simply be resolved by adding
moveis