Closed
Description
Consider this example (playground):
#![feature(async_await)]
use std::sync::Mutex;
fn is_send<T: Send>(t: T) {
}
async fn foo() {
bar(&Mutex::new(22)).await;
}
async fn bar(x: &Mutex<u32>) {
let g = x.lock().unwrap();
baz().await;
}
async fn baz() {
}
fn main() {
is_send(foo());
}
This program is in error because bar()
is holding a mutex guard (which is not Send
) live across the baz().await
call. The error however is rather opaque:
error[E0277]: `std::sync::MutexGuard<'_, u32>` cannot be sent between threads safely
--> src/main.rs:23:5
|
23 | is_send(foo());
| ^^^^^^^ `std::sync::MutexGuard<'_, u32>` cannot be sent between threads safely
|
= help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::sync::MutexGuard<'_, u32>`
= note: required because it appears within the type `for<'r, 's> {&'r std::sync::Mutex<u32>, std::sync::MutexGuard<'s, u32>, impl std::future::Future, ()}`
= note: required because it appears within the type `[static generator@src/main.rs:13:30: 16:2 x:&std::sync::Mutex<u32> for<'r, 's> {&'r std::sync::Mutex<u32>, std::sync::MutexGuard<'s, u32>, impl std::future::Future, ()}]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@src/main.rs:13:30: 16:2 x:&std::sync::Mutex<u32> for<'r, 's> {&'r std::sync::Mutex<u32>, std::sync::MutexGuard<'s, u32>, impl std::future::Future, ()}]>`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `for<'r> {impl std::future::Future, ()}`
= note: required because it appears within the type `[static generator@src/main.rs:9:16: 11:2 for<'r> {impl std::future::Future, ()}]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@src/main.rs:9:16: 11:2 for<'r> {impl std::future::Future, ()}]>`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `impl std::future::Future`
note: required by `is_send`
--> src/main.rs:5:1
|
5 | fn is_send<T: Send>(t: T) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
When discussing this error, @cramertj suggested that we might look for patterns like this and try to offer a customized error. They sketched out
error[E0277]: `foo()` cannot be sent between threads
note: the `is_send` function requires `T: Send`:
--> src/main.rs:5:1
|
5 | fn is_send<T: Send>(t: T) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
but in this invocation, the `foo()` is not `Send`
--> src/main.rs:23:5
|
23 | is_send(foo());
| ^^^^^
because it is of type `impl Future<Output = ()>`
which contains an `std::sync::MutexGuard<'_, u32>`
note: pass `--full-error-type-info` for more information
Something along these lines could be a big improvement!
Metadata
Metadata
Assignees
Labels
Area: Async & AwaitArea: Messages for errors, warnings, and lintsAsync-await issues that are part of the "polish" areaAsync-await issues that have been triaged during a working group meeting.Category: An issue proposing an enhancement or a PR with one.Relevant to the compiler team, which will review and decide on the PR/issue.