Skip to content

Improve await error messaging for trait obligations #71137

Closed
@rokob

Description

@rokob

I tried this code:

use std::future::Future;
use std::sync::Mutex;

fn fake_spawn<F: Future + Send + 'static>(f: F) { }

async fn wrong_mutex() {
  let m = Mutex::new(1);
  {
    let mut guard = m.lock().unwrap();
    (async { "right"; }).await;
    *guard += 1;
  }

  (async { "wrong"; }).await;
}

fn main() {
  fake_spawn(wrong_mutex());
}

I expected to see this happen:

error: future cannot be sent between threads safely
  --> src/main.rs:18:3
   |
4  | fn fake_spawn<F: Future + Send + 'static>(f: F) { }
   |    ----------             ---- required by this bound in `fake_spawn`
...
18 |   fake_spawn(wrong_mutex());
   |   ^^^^^^^^^^ future returned by `wrong_mutex` is not `Send`
   |
   = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::sync::MutexGuard<'_, i32>`
note: future is not `Send` as this value is used across an await
  --> src/main.rs:14:3
   |
9  |     let mut guard = m.lock().unwrap();
   |         --------- has type `std::sync::MutexGuard<'_, i32>`
...
12 |   }
   |   - `mut guard` is later dropped here
9  |     let mut guard = m.lock().unwrap();
10 |   (async { "right"; }).await;
   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^ await occurs here, with `mut guard` maybe used later

error: aborting due to previous error

Instead, this happened:

error: future cannot be sent between threads safely
  --> src/main.rs:18:3
   |
4  | fn fake_spawn<F: Future + Send + 'static>(f: F) { }
   |    ----------             ---- required by this bound in `fake_spawn`
...
18 |   fake_spawn(wrong_mutex());
   |   ^^^^^^^^^^ future returned by `wrong_mutex` is not `Send`
   |
   = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::sync::MutexGuard<'_, i32>`
note: future is not `Send` as this value is used across an await
  --> src/main.rs:14:3
   |
9  |     let mut guard = m.lock().unwrap();
   |         --------- has type `std::sync::MutexGuard<'_, i32>`
...
12 |   }
   |   - `mut guard` is later dropped here
13 |
14 |   (async { "wrong"; }).await;
   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^ await occurs here, with `mut guard` maybe used later

error: aborting due to previous error

Note that the await pointed to be the error message is wrong.

The code that gets the span for the await is here

let await_span = tables.generator_interior_types.iter().map(|t| t.span).last().unwrap();
. The last span in generator_interior_types is not guaranteed to be the right await point.

Meta

rustc --version --verbose:

rustc 1.42.0 (b8cedc004 2020-03-09)
binary: rustc
commit-hash: b8cedc00407a4c56a3bda1ed605c6fc166655447
commit-date: 2020-03-09
host: x86_64-apple-darwin
release: 1.42.0
LLVM version: 9.0

I also see the same behaviour with:

rustc 1.44.0-nightly (6dee5f112 2020-04-06)
binary: rustc
commit-hash: 6dee5f1126dfd5c9314ee5ae9d9eb010e35ef257
commit-date: 2020-04-06
host: x86_64-apple-darwin
release: 1.44.0-nightly
LLVM version: 9.0

Metadata

Metadata

Assignees

Labels

A-async-awaitArea: Async & AwaitA-diagnosticsArea: Messages for errors, warnings, and lintsAsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.C-bugCategory: This is a bug.P-mediumMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions