From 5381ddf4448bf8a201ac9514bf07a50102192a48 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Fri, 6 Dec 2019 23:57:57 -0500 Subject: [PATCH 1/9] Work on better error message --- src/librustc/traits/error_reporting.rs | 135 ++++++++++++++---- src/libstd/future.rs | 1 + .../ui/async-await/async-fn-nonsend.stderr | 91 ++++++------ .../ui/async-await/issue-64130-1-sync.stderr | 19 ++- .../ui/async-await/issue-64130-2-send.stderr | 19 ++- .../ui/async-await/issue-64130-3-other.stderr | 14 +- .../issue-64130-4-async-move.stderr | 24 ++-- .../issue-64130-non-send-future-diags.stderr | 24 ++-- src/test/ui/generator/not-send-sync.stderr | 15 +- 9 files changed, 201 insertions(+), 141 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 6a111895b5637..d7a29c7dba59c 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -32,6 +32,7 @@ use crate::ty::fast_reject; use crate::ty::fold::TypeFolder; use crate::ty::subst::Subst; use crate::ty::SubtypePredicate; +use crate::ty::TraitPredicate; use crate::util::nodemap::{FxHashMap, FxHashSet}; use errors::{Applicability, DiagnosticBuilder, pluralize, Style}; @@ -2103,12 +2104,28 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err: &mut DiagnosticBuilder<'_>, obligation: &PredicateObligation<'tcx>, ) { + + debug!("note_obligation_cause: obligation.predicate={:?} \ + obligation.cause.span={:?}", obligation.predicate, obligation.cause.span); + // First, attempt to add note to this error with an async-await-specific // message, and fall back to regular note otherwise. - if !self.maybe_note_obligation_cause_for_async_await(err, obligation) { - self.note_obligation_cause_code(err, &obligation.predicate, &obligation.cause.code, - &mut vec![]); + if let ty::Predicate::Trait(trait_predicate) = obligation.predicate { + if self.maybe_note_obligation_cause_for_async_await( + err, + trait_predicate.skip_binder(), + &obligation.cause.code + ) { + return; + } } + + self.note_obligation_cause_code( + err, + &obligation.predicate, + &obligation.cause.code, + &mut vec![] + ); } /// Adds an async-await specific note to the diagnostic when the future does not implement @@ -2156,12 +2173,25 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { fn maybe_note_obligation_cause_for_async_await( &self, err: &mut DiagnosticBuilder<'_>, - obligation: &PredicateObligation<'tcx>, + trait_predicate: &TraitPredicate<'tcx>, + code: &ObligationCauseCode<'tcx>, ) -> bool { - debug!("maybe_note_obligation_cause_for_async_await: obligation.predicate={:?} \ - obligation.cause.span={:?}", obligation.predicate, obligation.cause.span); + /*debug!("note_obligation_cause_for_async_await: obligation.predicate={:?} \ + obligation.cause.span={:?}", obligation.predicate, obligation.cause.span);*/ let source_map = self.tcx.sess.source_map(); + // Look into the obligation predicate to determine the type in the generator which meant + // that the predicate was not satisifed. + /*let (trait_ref, target_ty) = match obligation.predicate { + ty::Predicate::Trait(trait_predicate) => + (trait_predicate.skip_binder().trait_ref, trait_predicate.skip_binder().self_ty()), + _ => return false, + };*/ + + let (mut trait_ref, mut target_ty) = (trait_predicate.trait_ref, trait_predicate.self_ty()); + + debug!("note_obligation_cause_for_async_await: target_ty={:?}", target_ty); + // Attempt to detect an async-await error by looking at the obligation causes, looking // for a generator to be present. // @@ -2187,19 +2217,25 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // The first obligation in the chain is the most useful and has the generator that captured // the type. The last generator has information about where the bound was introduced. At // least one generator should be present for this diagnostic to be modified. - let (mut trait_ref, mut target_ty) = match obligation.predicate { - ty::Predicate::Trait(p) => - (Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty())), - _ => (None, None), - }; let mut generator = None; let mut last_generator = None; - let mut next_code = Some(&obligation.cause.code); + let mut next_code = Some(code); + let mut next_predicate = None; + + // First, find an `ObligationCause` code referencing a generator. + // Skip over intermediate causes generated by `.await` lowering while let Some(code) = next_code { debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code); match code { ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) | ObligationCauseCode::ImplDerivedObligation(derived_obligation) => { + + next_code = Some(derived_obligation.parent_code.as_ref()); + next_predicate = Some( + self.resolve_vars_if_possible(&derived_obligation.parent_trait_ref) + .to_predicate() + ); + let ty = derived_obligation.parent_trait_ref.self_ty(); debug!("maybe_note_obligation_cause_for_async_await: \ parent_trait_ref={:?} self_ty.kind={:?}", @@ -2212,25 +2248,55 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }, ty::GeneratorWitness(..) => {}, _ if generator.is_none() => { - trait_ref = Some(*derived_obligation.parent_trait_ref.skip_binder()); - target_ty = Some(ty); + trait_ref = *derived_obligation.parent_trait_ref.skip_binder(); + target_ty = ty; }, _ => {}, } + }, + _ => return false, + } + }; + + // Now that we've found a generator, try to determine if we should + // skip over any subsequence causes. + while let Some(code) = next_code { + debug!("note_obligation_cause_for_async_await: code={:?}", code); + match code { + ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) | + ObligationCauseCode::ImplDerivedObligation(derived_obligation) => { + debug!("note_obligation_cause_for_async_await: self_ty.kind={:?}", + derived_obligation.parent_trait_ref.self_ty().kind); + + + match derived_obligation.parent_trait_ref.self_ty().kind { + ty::Adt(ty::AdtDef { did, .. }, ..) if + self.tcx.is_diagnostic_item(sym::gen_future, *did) => {}, + ty::Opaque(did, _) if + self.tcx.parent(did).map(|parent| { + self.tcx.is_diagnostic_item(sym::from_generator, parent) + }).unwrap_or(false) => {} + _ => break, + } + next_code = Some(derived_obligation.parent_code.as_ref()); + next_predicate = Some( + self.resolve_vars_if_possible(&derived_obligation.parent_trait_ref) + .to_predicate() + ) }, - _ => break, + _ => break } } // Only continue if a generator was found. debug!("maybe_note_obligation_cause_for_async_await: generator={:?} trait_ref={:?} \ target_ty={:?}", generator, trait_ref, target_ty); - let (generator_did, trait_ref, target_ty) = match (generator, trait_ref, target_ty) { - (Some(generator_did), Some(trait_ref), Some(target_ty)) => - (generator_did, trait_ref, target_ty), - _ => return false, + let generator_did = if let Some(generator_did) = generator { + generator_did + } else { + return false; }; let span = self.tcx.def_span(generator_did); @@ -2290,7 +2356,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if let Some((target_span, Ok(snippet), scope_span)) = target_span { self.note_obligation_cause_for_async_await( err, *target_span, scope_span, snippet, generator_did, last_generator, - trait_ref, target_ty, tables, obligation, next_code, + trait_ref, target_ty, tables, &next_predicate.unwrap(), next_code, ); true } else { @@ -2311,7 +2377,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { trait_ref: ty::TraitRef<'_>, target_ty: Ty<'tcx>, tables: &ty::TypeckTables<'_>, - obligation: &PredicateObligation<'tcx>, + predicate: &ty::Predicate<'tcx>, next_code: Option<&ObligationCauseCode<'tcx>>, ) { let source_map = self.tcx.sess.source_map(); @@ -2342,9 +2408,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ("`Sync`", "shared") }; - err.clear_code(); - err.set_primary_message( - format!("future cannot be {} between threads safely", trait_verb) + err.note( + &format!("future cannot be {} between threads safely", trait_verb) ); let original_span = err.span.primary_span().unwrap(); @@ -2396,7 +2461,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { debug!("note_obligation_cause_for_async_await: next_code={:?}", next_code); self.note_obligation_cause_code( err, - &obligation.predicate, + &predicate, next_code.unwrap(), &mut Vec::new(), ); @@ -2410,6 +2475,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { where T: fmt::Display { let tcx = self.tcx; + + + let mut handle_async_await = |trait_ref, parent_code| { + self.maybe_note_obligation_cause_for_async_await( + err, + &TraitPredicate { trait_ref }, + parent_code + ) + }; + match *cause_code { ObligationCauseCode::ExprAssignable | ObligationCauseCode::MatchExpressionArm { .. } | @@ -2550,6 +2625,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } ObligationCauseCode::BuiltinDerivedObligation(ref data) => { let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref); + + if handle_async_await(*parent_trait_ref.skip_binder(), &data.parent_code) { + return; + } + let ty = parent_trait_ref.skip_binder().self_ty(); err.note(&format!("required because it appears within the type `{}`", ty)); obligated_types.push(ty); @@ -2564,6 +2644,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } ObligationCauseCode::ImplDerivedObligation(ref data) => { let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref); + + if handle_async_await(*parent_trait_ref.skip_binder(), &data.parent_code) { + return; + } + err.note( &format!("required because of the requirements on the impl of `{}` for `{}`", parent_trait_ref.print_only_trait_path(), diff --git a/src/libstd/future.rs b/src/libstd/future.rs index ac1ef3e1d8b72..4385f2dde3553 100644 --- a/src/libstd/future.rs +++ b/src/libstd/future.rs @@ -18,6 +18,7 @@ pub use core::future::*; /// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`). #[doc(hidden)] #[unstable(feature = "gen_future", issue = "50547")] +#[cfg_attr(not(test), rustc_diagnostic_item = "from_generator")] pub fn from_generator>(x: T) -> impl Future { GenFuture(x) } diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr index 5c870ca2d0276..6e89deb407e92 100644 --- a/src/test/ui/async-await/async-fn-nonsend.stderr +++ b/src/test/ui/async-await/async-fn-nonsend.stderr @@ -1,88 +1,79 @@ -error: future cannot be sent between threads safely +error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely --> $DIR/async-fn-nonsend.rs:50:5 | LL | fn assert_send(_: impl Send) {} | ----------- ---- required by this bound in `assert_send` ... LL | assert_send(local_dropped_before_await()); - | ^^^^^^^^^^^ future returned by `local_dropped_before_await` is not `Send` + | ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>` -note: future is not `Send` as this value is used across an await - --> $DIR/async-fn-nonsend.rs:25:5 - | -LL | let x = non_send(); - | - has type `impl std::fmt::Debug` -LL | drop(x); -LL | fut().await; - | ^^^^^^^^^^^ await occurs here, with `x` maybe used later -LL | } - | - `x` is later dropped here + = note: required because it appears within the type `impl std::fmt::Debug` + = note: required because it appears within the type `{impl std::fmt::Debug, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:21:39: 26:2 {impl std::fmt::Debug, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:21:39: 26:2 {impl std::fmt::Debug, impl std::future::Future, 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` -error: future cannot be sent between threads safely +error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely --> $DIR/async-fn-nonsend.rs:52:5 | LL | fn assert_send(_: impl Send) {} | ----------- ---- required by this bound in `assert_send` ... LL | assert_send(non_send_temporary_in_match()); - | ^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send` + | ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>` -note: future is not `Send` as this value is used across an await - --> $DIR/async-fn-nonsend.rs:34:20 - | -LL | match Some(non_send()) { - | ---------- has type `impl std::fmt::Debug` -LL | Some(_) => fut().await, - | ^^^^^^^^^^^ await occurs here, with `non_send()` maybe used later -... -LL | } - | - `non_send()` is later dropped here + = note: required because it appears within the type `impl std::fmt::Debug` + = note: required because it appears within the type `{impl std::fmt::Debug, std::option::Option, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:28:40: 37:2 {impl std::fmt::Debug, std::option::Option, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:28:40: 37:2 {impl std::fmt::Debug, std::option::Option, impl std::future::Future, 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` -error: future cannot be sent between threads safely +error[E0277]: `dyn std::fmt::Write` cannot be sent between threads safely --> $DIR/async-fn-nonsend.rs:54:5 | LL | fn assert_send(_: impl Send) {} | ----------- ---- required by this bound in `assert_send` ... LL | assert_send(non_sync_with_method_call()); - | ^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send` + | ^^^^^^^^^^^ `dyn std::fmt::Write` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `dyn std::fmt::Write` -note: future is not `Send` as this value is used across an await - --> $DIR/async-fn-nonsend.rs:43:9 - | -LL | let f: &mut std::fmt::Formatter = panic!(); - | - has type `&mut std::fmt::Formatter<'_>` -LL | if non_sync().fmt(f).unwrap() == () { -LL | fut().await; - | ^^^^^^^^^^^ await occurs here, with `f` maybe used later -LL | } -LL | } - | - `f` is later dropped here + = note: required because of the requirements on the impl of `std::marker::Send` for `&mut dyn std::fmt::Write` + = note: required because it appears within the type `std::fmt::Formatter<'_>` + = note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>` + = note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, 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` -error: future cannot be sent between threads safely +error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely --> $DIR/async-fn-nonsend.rs:54:5 | LL | fn assert_send(_: impl Send) {} | ----------- ---- required by this bound in `assert_send` ... LL | assert_send(non_sync_with_method_call()); - | ^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send` + | ^^^^^^^^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely | = help: within `std::fmt::ArgumentV1<'_>`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)` -note: future is not `Send` as this value is used across an await - --> $DIR/async-fn-nonsend.rs:43:9 - | -LL | let f: &mut std::fmt::Formatter = panic!(); - | - has type `&mut std::fmt::Formatter<'_>` -LL | if non_sync().fmt(f).unwrap() == () { -LL | fut().await; - | ^^^^^^^^^^^ await occurs here, with `f` maybe used later -LL | } -LL | } - | - `f` is later dropped here + = note: required because it appears within the type `std::marker::PhantomData<*mut (dyn std::ops::Fn() + 'static)>` + = note: required because it appears within the type `core::fmt::Void` + = note: required because it appears within the type `&core::fmt::Void` + = note: required because it appears within the type `std::fmt::ArgumentV1<'_>` + = note: required because of the requirements on the impl of `std::marker::Send` for `std::slice::Iter<'_, std::fmt::ArgumentV1<'_>>` + = note: required because it appears within the type `std::fmt::Formatter<'_>` + = note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>` + = note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, 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` error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/issue-64130-1-sync.stderr b/src/test/ui/async-await/issue-64130-1-sync.stderr index 8beb31f152a9d..c20038dcb7921 100644 --- a/src/test/ui/async-await/issue-64130-1-sync.stderr +++ b/src/test/ui/async-await/issue-64130-1-sync.stderr @@ -1,22 +1,19 @@ -error: future cannot be shared between threads safely +error[E0277]: `Foo` cannot be shared between threads safely --> $DIR/issue-64130-1-sync.rs:21:5 | LL | fn is_sync(t: T) { } | ------- ---- required by this bound in `is_sync` ... LL | is_sync(bar()); - | ^^^^^^^ future returned by `bar` is not `Sync` + | ^^^^^^^ `Foo` cannot be shared between threads safely | = help: within `impl std::future::Future`, the trait `std::marker::Sync` is not implemented for `Foo` -note: future is not `Sync` as this value is used across an await - --> $DIR/issue-64130-1-sync.rs:15:5 - | -LL | let x = Foo; - | - has type `Foo` -LL | baz().await; - | ^^^^^^^^^^^ await occurs here, with `x` maybe used later -LL | } - | - `x` is later dropped here + = note: required because it appears within the type `{Foo, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/issue-64130-1-sync.rs:13:16: 16:2 {Foo, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-1-sync.rs:13:16: 16:2 {Foo, impl std::future::Future, 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` error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/issue-64130-2-send.stderr b/src/test/ui/async-await/issue-64130-2-send.stderr index 823b88e18c5b6..c4ef7713aec93 100644 --- a/src/test/ui/async-await/issue-64130-2-send.stderr +++ b/src/test/ui/async-await/issue-64130-2-send.stderr @@ -1,22 +1,19 @@ -error: future cannot be sent between threads safely +error[E0277]: `Foo` cannot be sent between threads safely --> $DIR/issue-64130-2-send.rs:21:5 | LL | fn is_send(t: T) { } | ------- ---- required by this bound in `is_send` ... LL | is_send(bar()); - | ^^^^^^^ future returned by `bar` is not `Send` + | ^^^^^^^ `Foo` cannot be sent between threads safely | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `Foo` -note: future is not `Send` as this value is used across an await - --> $DIR/issue-64130-2-send.rs:15:5 - | -LL | let x = Foo; - | - has type `Foo` -LL | baz().await; - | ^^^^^^^^^^^ await occurs here, with `x` maybe used later -LL | } - | - `x` is later dropped here + = note: required because it appears within the type `{Foo, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/issue-64130-2-send.rs:13:16: 16:2 {Foo, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-2-send.rs:13:16: 16:2 {Foo, impl std::future::Future, 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` error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/issue-64130-3-other.stderr b/src/test/ui/async-await/issue-64130-3-other.stderr index 155c5cc8ea137..6fe6a54919352 100644 --- a/src/test/ui/async-await/issue-64130-3-other.stderr +++ b/src/test/ui/async-await/issue-64130-3-other.stderr @@ -9,15 +9,11 @@ LL | is_qux(bar()); | = help: the following implementations were found: -note: future does not implement `Qux` as this value is used across an await - --> $DIR/issue-64130-3-other.rs:17:5 - | -LL | let x = Foo; - | - has type `Foo` -LL | baz().await; - | ^^^^^^^^^^^ await occurs here, with `x` maybe used later -LL | } - | - `x` is later dropped here + = note: required because it appears within the type `{Foo, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/issue-64130-3-other.rs:15:16: 18:2 {Foo, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-3-other.rs:15:16: 18:2 {Foo, impl std::future::Future, 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` error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.stderr index ddbb469b99c24..fa244716a6863 100644 --- a/src/test/ui/async-await/issue-64130-4-async-move.stderr +++ b/src/test/ui/async-await/issue-64130-4-async-move.stderr @@ -1,22 +1,20 @@ -error: future cannot be sent between threads safely +error[E0277]: `(dyn std::any::Any + std::marker::Send + 'static)` cannot be shared between threads safely --> $DIR/issue-64130-4-async-move.rs:15:17 | LL | pub fn foo() -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^ future returned by `foo` is not `Send` + | ^^^^^^^^^^^^^^^^^^ `(dyn std::any::Any + std::marker::Send + 'static)` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `(dyn std::any::Any + std::marker::Send + 'static)` -note: future is not `Send` as this value is used across an await - --> $DIR/issue-64130-4-async-move.rs:21:26 - | -LL | match client.status() { - | ------ has type `&Client` -LL | 200 => { -LL | let _x = get().await; - | ^^^^^^^^^^^ await occurs here, with `client` maybe used later -... -LL | } - | - `client` is later dropped here + = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<(dyn std::any::Any + std::marker::Send + 'static)>` + = note: required because it appears within the type `std::boxed::Box<(dyn std::any::Any + std::marker::Send + 'static)>` + = note: required because it appears within the type `Client` + = note: required because of the requirements on the impl of `std::marker::Send` for `&Client` + = note: required because it appears within the type `for<'r> {&'r Client, Client, u16, u16, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/issue-64130-4-async-move.rs:18:16: 25:6 client:Client for<'r> {&'r Client, Client, u16, u16, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-4-async-move.rs:18:16: 25:6 client:Client for<'r> {&'r Client, Client, u16, u16, impl std::future::Future, impl std::future::Future, ()}]>` + = note: required because it appears within the type `impl std::future::Future` = note: the return type of a function must have a statically known size error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr index 662407f7017f5..3facff778660c 100644 --- a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr +++ b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr @@ -1,22 +1,24 @@ -error: future cannot be sent between threads safely +error[E0277]: `std::sync::MutexGuard<'_, u32>` cannot be sent between threads safely --> $DIR/issue-64130-non-send-future-diags.rs:21:5 | LL | fn is_send(t: T) { } | ------- ---- required by this bound in `is_send` ... LL | is_send(foo()); - | ^^^^^^^ future returned by `foo` is not `Send` + | ^^^^^^^ `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: future is not `Send` as this value is used across an await - --> $DIR/issue-64130-non-send-future-diags.rs:15:5 - | -LL | let g = x.lock().unwrap(); - | - has type `std::sync::MutexGuard<'_, u32>` -LL | baz().await; - | ^^^^^^^^^^^ await occurs here, with `g` maybe used later -LL | } - | - `g` is later dropped here + = note: required because it appears within the type `for<'r, 's> {&'r std::sync::Mutex, std::sync::MutexGuard<'s, u32>, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/issue-64130-non-send-future-diags.rs:13:30: 16:2 x:&std::sync::Mutex for<'r, 's> {&'r std::sync::Mutex, std::sync::MutexGuard<'s, u32>, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-non-send-future-diags.rs:13:30: 16:2 x:&std::sync::Mutex for<'r, 's> {&'r std::sync::Mutex, std::sync::MutexGuard<'s, u32>, impl std::future::Future, 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, 's, 't0, 't1> {u32, std::sync::Mutex, &'r std::sync::Mutex, &'s std::sync::Mutex, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/issue-64130-non-send-future-diags.rs:9:16: 11:2 for<'r, 's, 't0, 't1> {u32, std::sync::Mutex, &'r std::sync::Mutex, &'s std::sync::Mutex, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-non-send-future-diags.rs:9:16: 11:2 for<'r, 's, 't0, 't1> {u32, std::sync::Mutex, &'r std::sync::Mutex, &'s std::sync::Mutex, impl std::future::Future, 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` error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr index 0ac1d189b79b0..620db245d3e57 100644 --- a/src/test/ui/generator/not-send-sync.stderr +++ b/src/test/ui/generator/not-send-sync.stderr @@ -11,25 +11,18 @@ LL | assert_send(|| { = note: required because of the requirements on the impl of `std::marker::Send` for `&std::cell::Cell` = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:16:17: 20:6 a:&std::cell::Cell _]` -error: future cannot be shared between threads safely +error[E0277]: `std::cell::Cell` cannot be shared between threads safely --> $DIR/not-send-sync.rs:9:5 | LL | fn assert_sync(_: T) {} | ----------- ---- required by this bound in `main::assert_sync` ... LL | assert_sync(|| { - | ^^^^^^^^^^^ future returned by `main` is not `Sync` + | ^^^^^^^^^^^ `std::cell::Cell` cannot be shared between threads safely | = help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell, ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell` -note: future is not `Sync` as this value is used across an yield - --> $DIR/not-send-sync.rs:12:9 - | -LL | let a = Cell::new(2); - | - has type `std::cell::Cell` -LL | yield; - | ^^^^^ yield occurs here, with `a` maybe used later -LL | }); - | - `a` is later dropped here + = note: required because it appears within the type `{std::cell::Cell, ()}` + = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell, ()}]` error: aborting due to 2 previous errors From b135976fde48b8c77525186ec83486a2eb0420b4 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 12 Dec 2019 12:23:02 -0500 Subject: [PATCH 2/9] Some fixups --- src/librustc/traits/error_reporting.rs | 2 +- .../ui/async-await/async-fn-nonsend.stderr | 86 +++++++++++-------- .../ui/async-await/issue-64130-1-sync.stderr | 17 ++-- .../ui/async-await/issue-64130-2-send.stderr | 17 ++-- .../ui/async-await/issue-64130-3-other.stderr | 14 +-- .../issue-64130-4-async-move.stderr | 22 +++-- .../issue-64130-non-send-future-diags.stderr | 22 ++--- src/test/ui/generator/not-send-sync.stderr | 14 ++- 8 files changed, 117 insertions(+), 77 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index d7a29c7dba59c..73c63f67cf2f7 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -2255,7 +2255,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } }, - _ => return false, + _ => break, } }; diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr index 6e89deb407e92..3fb287754eba9 100644 --- a/src/test/ui/async-await/async-fn-nonsend.stderr +++ b/src/test/ui/async-await/async-fn-nonsend.stderr @@ -5,15 +5,20 @@ LL | fn assert_send(_: impl Send) {} | ----------- ---- required by this bound in `assert_send` ... LL | assert_send(local_dropped_before_await()); - | ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely + | ^^^^^^^^^^^ future returned by `local_dropped_before_await` is not `Send` | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>` - = note: required because it appears within the type `impl std::fmt::Debug` - = note: required because it appears within the type `{impl std::fmt::Debug, impl std::future::Future, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:21:39: 26:2 {impl std::fmt::Debug, impl std::future::Future, impl std::future::Future, ()}]` - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:21:39: 26:2 {impl std::fmt::Debug, impl std::future::Future, 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: future cannot be sent between threads safely +note: future is not `Send` as this value is used across an await + --> $DIR/async-fn-nonsend.rs:25:5 + | +LL | let x = non_send(); + | - has type `impl std::fmt::Debug` +LL | drop(x); +LL | fut().await; + | ^^^^^^^^^^^ await occurs here, with `x` maybe used later +LL | } + | - `x` is later dropped here error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely --> $DIR/async-fn-nonsend.rs:52:5 @@ -22,15 +27,20 @@ LL | fn assert_send(_: impl Send) {} | ----------- ---- required by this bound in `assert_send` ... LL | assert_send(non_send_temporary_in_match()); - | ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely + | ^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send` | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>` - = note: required because it appears within the type `impl std::fmt::Debug` - = note: required because it appears within the type `{impl std::fmt::Debug, std::option::Option, impl std::future::Future, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:28:40: 37:2 {impl std::fmt::Debug, std::option::Option, impl std::future::Future, impl std::future::Future, ()}]` - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:28:40: 37:2 {impl std::fmt::Debug, std::option::Option, impl std::future::Future, 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: future cannot be sent between threads safely +note: future is not `Send` as this value is used across an await + --> $DIR/async-fn-nonsend.rs:34:20 + | +LL | match Some(non_send()) { + | ---------- has type `impl std::fmt::Debug` +LL | Some(_) => fut().await, + | ^^^^^^^^^^^ await occurs here, with `non_send()` maybe used later +... +LL | } + | - `non_send()` is later dropped here error[E0277]: `dyn std::fmt::Write` cannot be sent between threads safely --> $DIR/async-fn-nonsend.rs:54:5 @@ -39,17 +49,21 @@ LL | fn assert_send(_: impl Send) {} | ----------- ---- required by this bound in `assert_send` ... LL | assert_send(non_sync_with_method_call()); - | ^^^^^^^^^^^ `dyn std::fmt::Write` cannot be sent between threads safely + | ^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send` | = help: the trait `std::marker::Send` is not implemented for `dyn std::fmt::Write` - = note: required because of the requirements on the impl of `std::marker::Send` for `&mut dyn std::fmt::Write` - = note: required because it appears within the type `std::fmt::Formatter<'_>` - = note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>` - = note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, impl std::future::Future, ()}]` - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, 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: future cannot be sent between threads safely +note: future is not `Send` as this value is used across an await + --> $DIR/async-fn-nonsend.rs:43:9 + | +LL | let f: &mut std::fmt::Formatter = panic!(); + | - has type `&mut std::fmt::Formatter<'_>` +LL | if non_sync().fmt(f).unwrap() == () { +LL | fut().await; + | ^^^^^^^^^^^ await occurs here, with `f` maybe used later +LL | } +LL | } + | - `f` is later dropped here error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely --> $DIR/async-fn-nonsend.rs:54:5 @@ -58,21 +72,21 @@ LL | fn assert_send(_: impl Send) {} | ----------- ---- required by this bound in `assert_send` ... LL | assert_send(non_sync_with_method_call()); - | ^^^^^^^^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely + | ^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send` | = help: within `std::fmt::ArgumentV1<'_>`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)` - = note: required because it appears within the type `std::marker::PhantomData<*mut (dyn std::ops::Fn() + 'static)>` - = note: required because it appears within the type `core::fmt::Void` - = note: required because it appears within the type `&core::fmt::Void` - = note: required because it appears within the type `std::fmt::ArgumentV1<'_>` - = note: required because of the requirements on the impl of `std::marker::Send` for `std::slice::Iter<'_, std::fmt::ArgumentV1<'_>>` - = note: required because it appears within the type `std::fmt::Formatter<'_>` - = note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>` - = note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, impl std::future::Future, ()}]` - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, 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: future cannot be sent between threads safely +note: future is not `Send` as this value is used across an await + --> $DIR/async-fn-nonsend.rs:43:9 + | +LL | let f: &mut std::fmt::Formatter = panic!(); + | - has type `&mut std::fmt::Formatter<'_>` +LL | if non_sync().fmt(f).unwrap() == () { +LL | fut().await; + | ^^^^^^^^^^^ await occurs here, with `f` maybe used later +LL | } +LL | } + | - `f` is later dropped here error: aborting due to 4 previous errors diff --git a/src/test/ui/async-await/issue-64130-1-sync.stderr b/src/test/ui/async-await/issue-64130-1-sync.stderr index c20038dcb7921..06a5eacafa74a 100644 --- a/src/test/ui/async-await/issue-64130-1-sync.stderr +++ b/src/test/ui/async-await/issue-64130-1-sync.stderr @@ -5,14 +5,19 @@ LL | fn is_sync(t: T) { } | ------- ---- required by this bound in `is_sync` ... LL | is_sync(bar()); - | ^^^^^^^ `Foo` cannot be shared between threads safely + | ^^^^^^^ future returned by `bar` is not `Sync` | = help: within `impl std::future::Future`, the trait `std::marker::Sync` is not implemented for `Foo` - = note: required because it appears within the type `{Foo, impl std::future::Future, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/issue-64130-1-sync.rs:13:16: 16:2 {Foo, impl std::future::Future, impl std::future::Future, ()}]` - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-1-sync.rs:13:16: 16:2 {Foo, impl std::future::Future, 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: future cannot be shared between threads safely +note: future is not `Sync` as this value is used across an await + --> $DIR/issue-64130-1-sync.rs:15:5 + | +LL | let x = Foo; + | - has type `Foo` +LL | baz().await; + | ^^^^^^^^^^^ await occurs here, with `x` maybe used later +LL | } + | - `x` is later dropped here error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-64130-2-send.stderr b/src/test/ui/async-await/issue-64130-2-send.stderr index c4ef7713aec93..879921e88b019 100644 --- a/src/test/ui/async-await/issue-64130-2-send.stderr +++ b/src/test/ui/async-await/issue-64130-2-send.stderr @@ -5,14 +5,19 @@ LL | fn is_send(t: T) { } | ------- ---- required by this bound in `is_send` ... LL | is_send(bar()); - | ^^^^^^^ `Foo` cannot be sent between threads safely + | ^^^^^^^ future returned by `bar` is not `Send` | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `Foo` - = note: required because it appears within the type `{Foo, impl std::future::Future, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/issue-64130-2-send.rs:13:16: 16:2 {Foo, impl std::future::Future, impl std::future::Future, ()}]` - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-2-send.rs:13:16: 16:2 {Foo, impl std::future::Future, 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: future cannot be sent between threads safely +note: future is not `Send` as this value is used across an await + --> $DIR/issue-64130-2-send.rs:15:5 + | +LL | let x = Foo; + | - has type `Foo` +LL | baz().await; + | ^^^^^^^^^^^ await occurs here, with `x` maybe used later +LL | } + | - `x` is later dropped here error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-64130-3-other.stderr b/src/test/ui/async-await/issue-64130-3-other.stderr index 6fe6a54919352..155c5cc8ea137 100644 --- a/src/test/ui/async-await/issue-64130-3-other.stderr +++ b/src/test/ui/async-await/issue-64130-3-other.stderr @@ -9,11 +9,15 @@ LL | is_qux(bar()); | = help: the following implementations were found: - = note: required because it appears within the type `{Foo, impl std::future::Future, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/issue-64130-3-other.rs:15:16: 18:2 {Foo, impl std::future::Future, impl std::future::Future, ()}]` - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-3-other.rs:15:16: 18:2 {Foo, impl std::future::Future, 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: future does not implement `Qux` as this value is used across an await + --> $DIR/issue-64130-3-other.rs:17:5 + | +LL | let x = Foo; + | - has type `Foo` +LL | baz().await; + | ^^^^^^^^^^^ await occurs here, with `x` maybe used later +LL | } + | - `x` is later dropped here error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.stderr index fa244716a6863..fec2f87b89e43 100644 --- a/src/test/ui/async-await/issue-64130-4-async-move.stderr +++ b/src/test/ui/async-await/issue-64130-4-async-move.stderr @@ -2,17 +2,21 @@ error[E0277]: `(dyn std::any::Any + std::marker::Send + 'static)` cannot be shar --> $DIR/issue-64130-4-async-move.rs:15:17 | LL | pub fn foo() -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^ `(dyn std::any::Any + std::marker::Send + 'static)` cannot be shared between threads safely + | ^^^^^^^^^^^^^^^^^^ future returned by `foo` is not `Send` | = help: the trait `std::marker::Sync` is not implemented for `(dyn std::any::Any + std::marker::Send + 'static)` - = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<(dyn std::any::Any + std::marker::Send + 'static)>` - = note: required because it appears within the type `std::boxed::Box<(dyn std::any::Any + std::marker::Send + 'static)>` - = note: required because it appears within the type `Client` - = note: required because of the requirements on the impl of `std::marker::Send` for `&Client` - = note: required because it appears within the type `for<'r> {&'r Client, Client, u16, u16, impl std::future::Future, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/issue-64130-4-async-move.rs:18:16: 25:6 client:Client for<'r> {&'r Client, Client, u16, u16, impl std::future::Future, impl std::future::Future, ()}]` - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-4-async-move.rs:18:16: 25:6 client:Client for<'r> {&'r Client, Client, u16, u16, impl std::future::Future, impl std::future::Future, ()}]>` - = note: required because it appears within the type `impl std::future::Future` + = note: future cannot be sent between threads safely +note: future is not `Send` as this value is used across an await + --> $DIR/issue-64130-4-async-move.rs:21:26 + | +LL | match client.status() { + | ------ has type `&Client` +LL | 200 => { +LL | let _x = get().await; + | ^^^^^^^^^^^ await occurs here, with `client` maybe used later +... +LL | } + | - `client` is later dropped here = note: the return type of a function must have a statically known size error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr index 3facff778660c..0168cd011ada9 100644 --- a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr +++ b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr @@ -5,19 +5,19 @@ LL | fn is_send(t: T) { } | ------- ---- required by this bound in `is_send` ... LL | is_send(foo()); - | ^^^^^^^ `std::sync::MutexGuard<'_, u32>` cannot be sent between threads safely + | ^^^^^^^ future returned by `foo` is not `Send` | = 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, std::sync::MutexGuard<'s, u32>, impl std::future::Future, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/issue-64130-non-send-future-diags.rs:13:30: 16:2 x:&std::sync::Mutex for<'r, 's> {&'r std::sync::Mutex, std::sync::MutexGuard<'s, u32>, impl std::future::Future, impl std::future::Future, ()}]` - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-non-send-future-diags.rs:13:30: 16:2 x:&std::sync::Mutex for<'r, 's> {&'r std::sync::Mutex, std::sync::MutexGuard<'s, u32>, impl std::future::Future, 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, 's, 't0, 't1> {u32, std::sync::Mutex, &'r std::sync::Mutex, &'s std::sync::Mutex, impl std::future::Future, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/issue-64130-non-send-future-diags.rs:9:16: 11:2 for<'r, 's, 't0, 't1> {u32, std::sync::Mutex, &'r std::sync::Mutex, &'s std::sync::Mutex, impl std::future::Future, impl std::future::Future, ()}]` - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-non-send-future-diags.rs:9:16: 11:2 for<'r, 's, 't0, 't1> {u32, std::sync::Mutex, &'r std::sync::Mutex, &'s std::sync::Mutex, impl std::future::Future, 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: future cannot be sent between threads safely +note: future is not `Send` as this value is used across an await + --> $DIR/issue-64130-non-send-future-diags.rs:15:5 + | +LL | let g = x.lock().unwrap(); + | - has type `std::sync::MutexGuard<'_, u32>` +LL | baz().await; + | ^^^^^^^^^^^ await occurs here, with `g` maybe used later +LL | } + | - `g` is later dropped here error: aborting due to previous error diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr index 620db245d3e57..74c6236a91aad 100644 --- a/src/test/ui/generator/not-send-sync.stderr +++ b/src/test/ui/generator/not-send-sync.stderr @@ -18,11 +18,19 @@ LL | fn assert_sync(_: T) {} | ----------- ---- required by this bound in `main::assert_sync` ... LL | assert_sync(|| { - | ^^^^^^^^^^^ `std::cell::Cell` cannot be shared between threads safely + | ^^^^^^^^^^^ future returned by `main` is not `Sync` | = help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell, ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell` - = note: required because it appears within the type `{std::cell::Cell, ()}` - = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell, ()}]` + = note: future cannot be shared between threads safely +note: future is not `Sync` as this value is used across an yield + --> $DIR/not-send-sync.rs:12:9 + | +LL | let a = Cell::new(2); + | - has type `std::cell::Cell` +LL | yield; + | ^^^^^ yield occurs here, with `a` maybe used later +LL | }); + | - `a` is later dropped here error: aborting due to 2 previous errors From 17d6d11ee772f0623e6bb7eeb5a28f6bc94cc85e Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 12 Dec 2019 12:40:12 -0500 Subject: [PATCH 3/9] Update error message position --- src/librustc/traits/error_reporting.rs | 2 +- src/test/ui/async-await/async-fn-nonsend.stderr | 12 ++++-------- src/test/ui/async-await/issue-64130-1-sync.stderr | 3 +-- src/test/ui/async-await/issue-64130-2-send.stderr | 3 +-- .../ui/async-await/issue-64130-4-async-move.stderr | 3 +-- .../issue-64130-non-send-future-diags.stderr | 3 +-- src/test/ui/generator/not-send-sync.stderr | 3 +-- 7 files changed, 10 insertions(+), 19 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 73c63f67cf2f7..9ec91cac9df3c 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -2408,7 +2408,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ("`Sync`", "shared") }; - err.note( + err.set_primary_message( &format!("future cannot be {} between threads safely", trait_verb) ); diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr index 3fb287754eba9..82f3a00059834 100644 --- a/src/test/ui/async-await/async-fn-nonsend.stderr +++ b/src/test/ui/async-await/async-fn-nonsend.stderr @@ -1,4 +1,4 @@ -error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely +error[E0277]: future cannot be sent between threads safely --> $DIR/async-fn-nonsend.rs:50:5 | LL | fn assert_send(_: impl Send) {} @@ -8,7 +8,6 @@ LL | assert_send(local_dropped_before_await()); | ^^^^^^^^^^^ future returned by `local_dropped_before_await` is not `Send` | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>` - = note: future cannot be sent between threads safely note: future is not `Send` as this value is used across an await --> $DIR/async-fn-nonsend.rs:25:5 | @@ -20,7 +19,7 @@ LL | fut().await; LL | } | - `x` is later dropped here -error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely +error[E0277]: future cannot be sent between threads safely --> $DIR/async-fn-nonsend.rs:52:5 | LL | fn assert_send(_: impl Send) {} @@ -30,7 +29,6 @@ LL | assert_send(non_send_temporary_in_match()); | ^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send` | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>` - = note: future cannot be sent between threads safely note: future is not `Send` as this value is used across an await --> $DIR/async-fn-nonsend.rs:34:20 | @@ -42,7 +40,7 @@ LL | Some(_) => fut().await, LL | } | - `non_send()` is later dropped here -error[E0277]: `dyn std::fmt::Write` cannot be sent between threads safely +error[E0277]: future cannot be sent between threads safely --> $DIR/async-fn-nonsend.rs:54:5 | LL | fn assert_send(_: impl Send) {} @@ -52,7 +50,6 @@ LL | assert_send(non_sync_with_method_call()); | ^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send` | = help: the trait `std::marker::Send` is not implemented for `dyn std::fmt::Write` - = note: future cannot be sent between threads safely note: future is not `Send` as this value is used across an await --> $DIR/async-fn-nonsend.rs:43:9 | @@ -65,7 +62,7 @@ LL | } LL | } | - `f` is later dropped here -error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely +error[E0277]: future cannot be sent between threads safely --> $DIR/async-fn-nonsend.rs:54:5 | LL | fn assert_send(_: impl Send) {} @@ -75,7 +72,6 @@ LL | assert_send(non_sync_with_method_call()); | ^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send` | = help: within `std::fmt::ArgumentV1<'_>`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)` - = note: future cannot be sent between threads safely note: future is not `Send` as this value is used across an await --> $DIR/async-fn-nonsend.rs:43:9 | diff --git a/src/test/ui/async-await/issue-64130-1-sync.stderr b/src/test/ui/async-await/issue-64130-1-sync.stderr index 06a5eacafa74a..0ea1f3537d18f 100644 --- a/src/test/ui/async-await/issue-64130-1-sync.stderr +++ b/src/test/ui/async-await/issue-64130-1-sync.stderr @@ -1,4 +1,4 @@ -error[E0277]: `Foo` cannot be shared between threads safely +error[E0277]: future cannot be shared between threads safely --> $DIR/issue-64130-1-sync.rs:21:5 | LL | fn is_sync(t: T) { } @@ -8,7 +8,6 @@ LL | is_sync(bar()); | ^^^^^^^ future returned by `bar` is not `Sync` | = help: within `impl std::future::Future`, the trait `std::marker::Sync` is not implemented for `Foo` - = note: future cannot be shared between threads safely note: future is not `Sync` as this value is used across an await --> $DIR/issue-64130-1-sync.rs:15:5 | diff --git a/src/test/ui/async-await/issue-64130-2-send.stderr b/src/test/ui/async-await/issue-64130-2-send.stderr index 879921e88b019..82669bf643303 100644 --- a/src/test/ui/async-await/issue-64130-2-send.stderr +++ b/src/test/ui/async-await/issue-64130-2-send.stderr @@ -1,4 +1,4 @@ -error[E0277]: `Foo` cannot be sent between threads safely +error[E0277]: future cannot be sent between threads safely --> $DIR/issue-64130-2-send.rs:21:5 | LL | fn is_send(t: T) { } @@ -8,7 +8,6 @@ LL | is_send(bar()); | ^^^^^^^ future returned by `bar` is not `Send` | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `Foo` - = note: future cannot be sent between threads safely note: future is not `Send` as this value is used across an await --> $DIR/issue-64130-2-send.rs:15:5 | diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.stderr index fec2f87b89e43..60303fc2ebc03 100644 --- a/src/test/ui/async-await/issue-64130-4-async-move.stderr +++ b/src/test/ui/async-await/issue-64130-4-async-move.stderr @@ -1,11 +1,10 @@ -error[E0277]: `(dyn std::any::Any + std::marker::Send + 'static)` cannot be shared between threads safely +error[E0277]: future cannot be sent between threads safely --> $DIR/issue-64130-4-async-move.rs:15:17 | LL | pub fn foo() -> impl Future + Send { | ^^^^^^^^^^^^^^^^^^ future returned by `foo` is not `Send` | = help: the trait `std::marker::Sync` is not implemented for `(dyn std::any::Any + std::marker::Send + 'static)` - = note: future cannot be sent between threads safely note: future is not `Send` as this value is used across an await --> $DIR/issue-64130-4-async-move.rs:21:26 | diff --git a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr index 0168cd011ada9..78ee3173bcb96 100644 --- a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr +++ b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr @@ -1,4 +1,4 @@ -error[E0277]: `std::sync::MutexGuard<'_, u32>` cannot be sent between threads safely +error[E0277]: future cannot be sent between threads safely --> $DIR/issue-64130-non-send-future-diags.rs:21:5 | LL | fn is_send(t: T) { } @@ -8,7 +8,6 @@ LL | is_send(foo()); | ^^^^^^^ future returned by `foo` is not `Send` | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::sync::MutexGuard<'_, u32>` - = note: future cannot be sent between threads safely note: future is not `Send` as this value is used across an await --> $DIR/issue-64130-non-send-future-diags.rs:15:5 | diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr index 74c6236a91aad..aa7fe971f13d9 100644 --- a/src/test/ui/generator/not-send-sync.stderr +++ b/src/test/ui/generator/not-send-sync.stderr @@ -11,7 +11,7 @@ LL | assert_send(|| { = note: required because of the requirements on the impl of `std::marker::Send` for `&std::cell::Cell` = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:16:17: 20:6 a:&std::cell::Cell _]` -error[E0277]: `std::cell::Cell` cannot be shared between threads safely +error[E0277]: future cannot be shared between threads safely --> $DIR/not-send-sync.rs:9:5 | LL | fn assert_sync(_: T) {} @@ -21,7 +21,6 @@ LL | assert_sync(|| { | ^^^^^^^^^^^ future returned by `main` is not `Sync` | = help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell, ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell` - = note: future cannot be shared between threads safely note: future is not `Sync` as this value is used across an yield --> $DIR/not-send-sync.rs:12:9 | From 151bae9e24c7a0953a9d0a8fae7298b8c56acbba Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 12 Dec 2019 17:08:02 -0500 Subject: [PATCH 4/9] Some more owkr --- src/librustc/traits/error_reporting.rs | 4 +- .../ui/async-await/async-fn-nonsend.stderr | 90 +++++++++---------- .../ui/async-await/issue-64130-1-sync.stderr | 18 ++-- .../ui/async-await/issue-64130-2-send.stderr | 18 ++-- .../ui/async-await/issue-64130-3-other.stderr | 14 ++- .../issue-64130-4-async-move.stderr | 23 +++-- .../issue-64130-non-send-future-diags.stderr | 23 ++--- src/test/ui/generator/not-send-sync.stderr | 15 +--- 8 files changed, 87 insertions(+), 118 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 9ec91cac9df3c..8b02d404a4084 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -2251,11 +2251,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { trait_ref = *derived_obligation.parent_trait_ref.skip_binder(); target_ty = ty; }, - _ => {}, + _ => return false, } }, - _ => break, + _ => return false, } }; diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr index 82f3a00059834..6e89deb407e92 100644 --- a/src/test/ui/async-await/async-fn-nonsend.stderr +++ b/src/test/ui/async-await/async-fn-nonsend.stderr @@ -1,88 +1,78 @@ -error[E0277]: future cannot be sent between threads safely +error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely --> $DIR/async-fn-nonsend.rs:50:5 | LL | fn assert_send(_: impl Send) {} | ----------- ---- required by this bound in `assert_send` ... LL | assert_send(local_dropped_before_await()); - | ^^^^^^^^^^^ future returned by `local_dropped_before_await` is not `Send` + | ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>` -note: future is not `Send` as this value is used across an await - --> $DIR/async-fn-nonsend.rs:25:5 - | -LL | let x = non_send(); - | - has type `impl std::fmt::Debug` -LL | drop(x); -LL | fut().await; - | ^^^^^^^^^^^ await occurs here, with `x` maybe used later -LL | } - | - `x` is later dropped here + = note: required because it appears within the type `impl std::fmt::Debug` + = note: required because it appears within the type `{impl std::fmt::Debug, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:21:39: 26:2 {impl std::fmt::Debug, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:21:39: 26:2 {impl std::fmt::Debug, impl std::future::Future, 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` -error[E0277]: future cannot be sent between threads safely +error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely --> $DIR/async-fn-nonsend.rs:52:5 | LL | fn assert_send(_: impl Send) {} | ----------- ---- required by this bound in `assert_send` ... LL | assert_send(non_send_temporary_in_match()); - | ^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send` + | ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>` -note: future is not `Send` as this value is used across an await - --> $DIR/async-fn-nonsend.rs:34:20 - | -LL | match Some(non_send()) { - | ---------- has type `impl std::fmt::Debug` -LL | Some(_) => fut().await, - | ^^^^^^^^^^^ await occurs here, with `non_send()` maybe used later -... -LL | } - | - `non_send()` is later dropped here + = note: required because it appears within the type `impl std::fmt::Debug` + = note: required because it appears within the type `{impl std::fmt::Debug, std::option::Option, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:28:40: 37:2 {impl std::fmt::Debug, std::option::Option, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:28:40: 37:2 {impl std::fmt::Debug, std::option::Option, impl std::future::Future, 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` -error[E0277]: future cannot be sent between threads safely +error[E0277]: `dyn std::fmt::Write` cannot be sent between threads safely --> $DIR/async-fn-nonsend.rs:54:5 | LL | fn assert_send(_: impl Send) {} | ----------- ---- required by this bound in `assert_send` ... LL | assert_send(non_sync_with_method_call()); - | ^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send` + | ^^^^^^^^^^^ `dyn std::fmt::Write` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `dyn std::fmt::Write` -note: future is not `Send` as this value is used across an await - --> $DIR/async-fn-nonsend.rs:43:9 - | -LL | let f: &mut std::fmt::Formatter = panic!(); - | - has type `&mut std::fmt::Formatter<'_>` -LL | if non_sync().fmt(f).unwrap() == () { -LL | fut().await; - | ^^^^^^^^^^^ await occurs here, with `f` maybe used later -LL | } -LL | } - | - `f` is later dropped here + = note: required because of the requirements on the impl of `std::marker::Send` for `&mut dyn std::fmt::Write` + = note: required because it appears within the type `std::fmt::Formatter<'_>` + = note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>` + = note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, 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` -error[E0277]: future cannot be sent between threads safely +error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely --> $DIR/async-fn-nonsend.rs:54:5 | LL | fn assert_send(_: impl Send) {} | ----------- ---- required by this bound in `assert_send` ... LL | assert_send(non_sync_with_method_call()); - | ^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send` + | ^^^^^^^^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely | = help: within `std::fmt::ArgumentV1<'_>`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)` -note: future is not `Send` as this value is used across an await - --> $DIR/async-fn-nonsend.rs:43:9 - | -LL | let f: &mut std::fmt::Formatter = panic!(); - | - has type `&mut std::fmt::Formatter<'_>` -LL | if non_sync().fmt(f).unwrap() == () { -LL | fut().await; - | ^^^^^^^^^^^ await occurs here, with `f` maybe used later -LL | } -LL | } - | - `f` is later dropped here + = note: required because it appears within the type `std::marker::PhantomData<*mut (dyn std::ops::Fn() + 'static)>` + = note: required because it appears within the type `core::fmt::Void` + = note: required because it appears within the type `&core::fmt::Void` + = note: required because it appears within the type `std::fmt::ArgumentV1<'_>` + = note: required because of the requirements on the impl of `std::marker::Send` for `std::slice::Iter<'_, std::fmt::ArgumentV1<'_>>` + = note: required because it appears within the type `std::fmt::Formatter<'_>` + = note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>` + = note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, 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` error: aborting due to 4 previous errors diff --git a/src/test/ui/async-await/issue-64130-1-sync.stderr b/src/test/ui/async-await/issue-64130-1-sync.stderr index 0ea1f3537d18f..c20038dcb7921 100644 --- a/src/test/ui/async-await/issue-64130-1-sync.stderr +++ b/src/test/ui/async-await/issue-64130-1-sync.stderr @@ -1,22 +1,18 @@ -error[E0277]: future cannot be shared between threads safely +error[E0277]: `Foo` cannot be shared between threads safely --> $DIR/issue-64130-1-sync.rs:21:5 | LL | fn is_sync(t: T) { } | ------- ---- required by this bound in `is_sync` ... LL | is_sync(bar()); - | ^^^^^^^ future returned by `bar` is not `Sync` + | ^^^^^^^ `Foo` cannot be shared between threads safely | = help: within `impl std::future::Future`, the trait `std::marker::Sync` is not implemented for `Foo` -note: future is not `Sync` as this value is used across an await - --> $DIR/issue-64130-1-sync.rs:15:5 - | -LL | let x = Foo; - | - has type `Foo` -LL | baz().await; - | ^^^^^^^^^^^ await occurs here, with `x` maybe used later -LL | } - | - `x` is later dropped here + = note: required because it appears within the type `{Foo, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/issue-64130-1-sync.rs:13:16: 16:2 {Foo, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-1-sync.rs:13:16: 16:2 {Foo, impl std::future::Future, 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` error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-64130-2-send.stderr b/src/test/ui/async-await/issue-64130-2-send.stderr index 82669bf643303..c4ef7713aec93 100644 --- a/src/test/ui/async-await/issue-64130-2-send.stderr +++ b/src/test/ui/async-await/issue-64130-2-send.stderr @@ -1,22 +1,18 @@ -error[E0277]: future cannot be sent between threads safely +error[E0277]: `Foo` cannot be sent between threads safely --> $DIR/issue-64130-2-send.rs:21:5 | LL | fn is_send(t: T) { } | ------- ---- required by this bound in `is_send` ... LL | is_send(bar()); - | ^^^^^^^ future returned by `bar` is not `Send` + | ^^^^^^^ `Foo` cannot be sent between threads safely | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `Foo` -note: future is not `Send` as this value is used across an await - --> $DIR/issue-64130-2-send.rs:15:5 - | -LL | let x = Foo; - | - has type `Foo` -LL | baz().await; - | ^^^^^^^^^^^ await occurs here, with `x` maybe used later -LL | } - | - `x` is later dropped here + = note: required because it appears within the type `{Foo, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/issue-64130-2-send.rs:13:16: 16:2 {Foo, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-2-send.rs:13:16: 16:2 {Foo, impl std::future::Future, 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` error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-64130-3-other.stderr b/src/test/ui/async-await/issue-64130-3-other.stderr index 155c5cc8ea137..6fe6a54919352 100644 --- a/src/test/ui/async-await/issue-64130-3-other.stderr +++ b/src/test/ui/async-await/issue-64130-3-other.stderr @@ -9,15 +9,11 @@ LL | is_qux(bar()); | = help: the following implementations were found: -note: future does not implement `Qux` as this value is used across an await - --> $DIR/issue-64130-3-other.rs:17:5 - | -LL | let x = Foo; - | - has type `Foo` -LL | baz().await; - | ^^^^^^^^^^^ await occurs here, with `x` maybe used later -LL | } - | - `x` is later dropped here + = note: required because it appears within the type `{Foo, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/issue-64130-3-other.rs:15:16: 18:2 {Foo, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-3-other.rs:15:16: 18:2 {Foo, impl std::future::Future, 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` error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.stderr index 60303fc2ebc03..fa244716a6863 100644 --- a/src/test/ui/async-await/issue-64130-4-async-move.stderr +++ b/src/test/ui/async-await/issue-64130-4-async-move.stderr @@ -1,21 +1,18 @@ -error[E0277]: future cannot be sent between threads safely +error[E0277]: `(dyn std::any::Any + std::marker::Send + 'static)` cannot be shared between threads safely --> $DIR/issue-64130-4-async-move.rs:15:17 | LL | pub fn foo() -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^ future returned by `foo` is not `Send` + | ^^^^^^^^^^^^^^^^^^ `(dyn std::any::Any + std::marker::Send + 'static)` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `(dyn std::any::Any + std::marker::Send + 'static)` -note: future is not `Send` as this value is used across an await - --> $DIR/issue-64130-4-async-move.rs:21:26 - | -LL | match client.status() { - | ------ has type `&Client` -LL | 200 => { -LL | let _x = get().await; - | ^^^^^^^^^^^ await occurs here, with `client` maybe used later -... -LL | } - | - `client` is later dropped here + = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<(dyn std::any::Any + std::marker::Send + 'static)>` + = note: required because it appears within the type `std::boxed::Box<(dyn std::any::Any + std::marker::Send + 'static)>` + = note: required because it appears within the type `Client` + = note: required because of the requirements on the impl of `std::marker::Send` for `&Client` + = note: required because it appears within the type `for<'r> {&'r Client, Client, u16, u16, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/issue-64130-4-async-move.rs:18:16: 25:6 client:Client for<'r> {&'r Client, Client, u16, u16, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-4-async-move.rs:18:16: 25:6 client:Client for<'r> {&'r Client, Client, u16, u16, impl std::future::Future, impl std::future::Future, ()}]>` + = note: required because it appears within the type `impl std::future::Future` = note: the return type of a function must have a statically known size error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr index 78ee3173bcb96..3facff778660c 100644 --- a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr +++ b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr @@ -1,22 +1,23 @@ -error[E0277]: future cannot be sent between threads safely +error[E0277]: `std::sync::MutexGuard<'_, u32>` cannot be sent between threads safely --> $DIR/issue-64130-non-send-future-diags.rs:21:5 | LL | fn is_send(t: T) { } | ------- ---- required by this bound in `is_send` ... LL | is_send(foo()); - | ^^^^^^^ future returned by `foo` is not `Send` + | ^^^^^^^ `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: future is not `Send` as this value is used across an await - --> $DIR/issue-64130-non-send-future-diags.rs:15:5 - | -LL | let g = x.lock().unwrap(); - | - has type `std::sync::MutexGuard<'_, u32>` -LL | baz().await; - | ^^^^^^^^^^^ await occurs here, with `g` maybe used later -LL | } - | - `g` is later dropped here + = note: required because it appears within the type `for<'r, 's> {&'r std::sync::Mutex, std::sync::MutexGuard<'s, u32>, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/issue-64130-non-send-future-diags.rs:13:30: 16:2 x:&std::sync::Mutex for<'r, 's> {&'r std::sync::Mutex, std::sync::MutexGuard<'s, u32>, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-non-send-future-diags.rs:13:30: 16:2 x:&std::sync::Mutex for<'r, 's> {&'r std::sync::Mutex, std::sync::MutexGuard<'s, u32>, impl std::future::Future, 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, 's, 't0, 't1> {u32, std::sync::Mutex, &'r std::sync::Mutex, &'s std::sync::Mutex, impl std::future::Future, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/issue-64130-non-send-future-diags.rs:9:16: 11:2 for<'r, 's, 't0, 't1> {u32, std::sync::Mutex, &'r std::sync::Mutex, &'s std::sync::Mutex, impl std::future::Future, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-non-send-future-diags.rs:9:16: 11:2 for<'r, 's, 't0, 't1> {u32, std::sync::Mutex, &'r std::sync::Mutex, &'s std::sync::Mutex, impl std::future::Future, 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` error: aborting due to previous error diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr index aa7fe971f13d9..620db245d3e57 100644 --- a/src/test/ui/generator/not-send-sync.stderr +++ b/src/test/ui/generator/not-send-sync.stderr @@ -11,25 +11,18 @@ LL | assert_send(|| { = note: required because of the requirements on the impl of `std::marker::Send` for `&std::cell::Cell` = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:16:17: 20:6 a:&std::cell::Cell _]` -error[E0277]: future cannot be shared between threads safely +error[E0277]: `std::cell::Cell` cannot be shared between threads safely --> $DIR/not-send-sync.rs:9:5 | LL | fn assert_sync(_: T) {} | ----------- ---- required by this bound in `main::assert_sync` ... LL | assert_sync(|| { - | ^^^^^^^^^^^ future returned by `main` is not `Sync` + | ^^^^^^^^^^^ `std::cell::Cell` cannot be shared between threads safely | = help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell, ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell` -note: future is not `Sync` as this value is used across an yield - --> $DIR/not-send-sync.rs:12:9 - | -LL | let a = Cell::new(2); - | - has type `std::cell::Cell` -LL | yield; - | ^^^^^ yield occurs here, with `a` maybe used later -LL | }); - | - `a` is later dropped here + = note: required because it appears within the type `{std::cell::Cell, ()}` + = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell, ()}]` error: aborting due to 2 previous errors From 396082673c7d0f89348a815a836bd4a6ebbfb8d7 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 12 Dec 2019 17:29:11 -0500 Subject: [PATCH 5/9] Work told old behavior --- src/librustc/traits/error_reporting.rs | 69 ++++++++++++------ .../ui/async-await/async-fn-nonsend.stderr | 70 +++++++++++++------ .../ui/async-await/issue-64130-1-sync.stderr | 15 ++-- .../ui/async-await/issue-64130-2-send.stderr | 15 ++-- .../ui/async-await/issue-64130-3-other.stderr | 11 ++- .../issue-64130-4-async-move.stderr | 18 +++-- .../issue-64130-non-send-future-diags.stderr | 26 +++++-- src/test/ui/generator/not-send-sync.stderr | 15 ++-- 8 files changed, 171 insertions(+), 68 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 8b02d404a4084..367912a239334 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -2225,10 +2225,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // First, find an `ObligationCause` code referencing a generator. // Skip over intermediate causes generated by `.await` lowering while let Some(code) = next_code { - debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code); + debug!("note_obligation_cause_for_async_await: code={:?}", code); match code { ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) | ObligationCauseCode::ImplDerivedObligation(derived_obligation) => { + debug!("note_obligation_cause_for_async_await: self_ty.kind={:?}", + derived_obligation.parent_trait_ref.self_ty().kind); next_code = Some(derived_obligation.parent_code.as_ref()); next_predicate = Some( @@ -2236,21 +2238,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .to_predicate() ); - let ty = derived_obligation.parent_trait_ref.self_ty(); - debug!("maybe_note_obligation_cause_for_async_await: \ - parent_trait_ref={:?} self_ty.kind={:?}", - derived_obligation.parent_trait_ref, ty.kind); - - match ty.kind { + match derived_obligation.parent_trait_ref.self_ty().kind { + ty::Adt(ty::AdtDef { did, .. }, ..) if + self.tcx.is_diagnostic_item(sym::gen_future, *did) => {}, ty::Generator(did, ..) => { - generator = generator.or(Some(did)); - last_generator = Some(did); - }, - ty::GeneratorWitness(..) => {}, - _ if generator.is_none() => { - trait_ref = *derived_obligation.parent_trait_ref.skip_binder(); - target_ty = ty; + debug!("note_obligation_cause_for_async_await: found generator {:?}", + generator); + generator = Some(did); + break; }, + ty::GeneratorWitness(_) | ty::Opaque(..) => {}, _ => return false, } @@ -2290,14 +2287,42 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - // Only continue if a generator was found. - debug!("maybe_note_obligation_cause_for_async_await: generator={:?} trait_ref={:?} \ - target_ty={:?}", generator, trait_ref, target_ty); - let generator_did = if let Some(generator_did) = generator { - generator_did - } else { - return false; - }; + + + // Now that we've found a generator, try to determine if we should + // skip over any subsequence causes. + while let Some(code) = next_code { + debug!("note_obligation_cause_for_async_await: code={:?}", code); + match code { + ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) | + ObligationCauseCode::ImplDerivedObligation(derived_obligation) => { + debug!("note_obligation_cause_for_async_await: self_ty.kind={:?}", + derived_obligation.parent_trait_ref.self_ty().kind); + + + match derived_obligation.parent_trait_ref.self_ty().kind { + ty::Adt(ty::AdtDef { did, .. }, ..) if + self.tcx.is_diagnostic_item(sym::gen_future, *did) => {}, + ty::Opaque(did, _) if + self.tcx.parent(did).map(|parent| { + self.tcx.is_diagnostic_item(sym::from_generator, parent) + }).unwrap_or(false) => {} + _ => break, + } + + next_code = Some(derived_obligation.parent_code.as_ref()); + next_predicate = Some( + self.resolve_vars_if_possible(&derived_obligation.parent_trait_ref) + .to_predicate() + ) + }, + _ => break + } + } + + + let generator_did = generator.expect("can only reach this if there was a generator"); + let span = self.tcx.def_span(generator_did); diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr index 6e89deb407e92..43ea77c580b6f 100644 --- a/src/test/ui/async-await/async-fn-nonsend.stderr +++ b/src/test/ui/async-await/async-fn-nonsend.stderr @@ -1,64 +1,86 @@ -error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely +error[E0277]: future cannot be sent between threads safely --> $DIR/async-fn-nonsend.rs:50:5 | LL | fn assert_send(_: impl Send) {} | ----------- ---- required by this bound in `assert_send` ... LL | assert_send(local_dropped_before_await()); - | ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely + | ^^^^^^^^^^^ future is not `Send` | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>` - = note: required because it appears within the type `impl std::fmt::Debug` - = note: required because it appears within the type `{impl std::fmt::Debug, impl std::future::Future, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:21:39: 26:2 {impl std::fmt::Debug, impl std::future::Future, impl std::future::Future, ()}]` +note: future is not `Send` as this value is used across an await + --> $DIR/async-fn-nonsend.rs:25:5 + | +LL | let x = non_send(); + | - has type `impl std::fmt::Debug` +LL | drop(x); +LL | fut().await; + | ^^^^^^^^^^^ await occurs here, with `x` maybe used later +LL | } + | - `x` is later dropped here = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:21:39: 26:2 {impl std::fmt::Debug, impl std::future::Future, 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` -error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely +error[E0277]: future cannot be sent between threads safely --> $DIR/async-fn-nonsend.rs:52:5 | LL | fn assert_send(_: impl Send) {} | ----------- ---- required by this bound in `assert_send` ... LL | assert_send(non_send_temporary_in_match()); - | ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely + | ^^^^^^^^^^^ future is not `Send` | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>` - = note: required because it appears within the type `impl std::fmt::Debug` - = note: required because it appears within the type `{impl std::fmt::Debug, std::option::Option, impl std::future::Future, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:28:40: 37:2 {impl std::fmt::Debug, std::option::Option, impl std::future::Future, impl std::future::Future, ()}]` +note: future is not `Send` as this value is used across an await + --> $DIR/async-fn-nonsend.rs:34:20 + | +LL | match Some(non_send()) { + | ---------- has type `impl std::fmt::Debug` +LL | Some(_) => fut().await, + | ^^^^^^^^^^^ await occurs here, with `non_send()` maybe used later +... +LL | } + | - `non_send()` is later dropped here = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:28:40: 37:2 {impl std::fmt::Debug, std::option::Option, impl std::future::Future, 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` -error[E0277]: `dyn std::fmt::Write` cannot be sent between threads safely +error[E0277]: future cannot be sent between threads safely --> $DIR/async-fn-nonsend.rs:54:5 | LL | fn assert_send(_: impl Send) {} | ----------- ---- required by this bound in `assert_send` ... LL | assert_send(non_sync_with_method_call()); - | ^^^^^^^^^^^ `dyn std::fmt::Write` cannot be sent between threads safely + | ^^^^^^^^^^^ future is not `Send` | = help: the trait `std::marker::Send` is not implemented for `dyn std::fmt::Write` = note: required because of the requirements on the impl of `std::marker::Send` for `&mut dyn std::fmt::Write` = note: required because it appears within the type `std::fmt::Formatter<'_>` - = note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>` - = note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, impl std::future::Future, ()}]` +note: future is not `Send` as this value is used across an await + --> $DIR/async-fn-nonsend.rs:43:9 + | +LL | let f: &mut std::fmt::Formatter = panic!(); + | - has type `&mut std::fmt::Formatter<'_>` +LL | if non_sync().fmt(f).unwrap() == () { +LL | fut().await; + | ^^^^^^^^^^^ await occurs here, with `f` maybe used later +LL | } +LL | } + | - `f` is later dropped here = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, 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` -error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely +error[E0277]: future cannot be sent between threads safely --> $DIR/async-fn-nonsend.rs:54:5 | LL | fn assert_send(_: impl Send) {} | ----------- ---- required by this bound in `assert_send` ... LL | assert_send(non_sync_with_method_call()); - | ^^^^^^^^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely + | ^^^^^^^^^^^ future is not `Send` | = help: within `std::fmt::ArgumentV1<'_>`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)` = note: required because it appears within the type `std::marker::PhantomData<*mut (dyn std::ops::Fn() + 'static)>` @@ -67,9 +89,17 @@ LL | assert_send(non_sync_with_method_call()); = note: required because it appears within the type `std::fmt::ArgumentV1<'_>` = note: required because of the requirements on the impl of `std::marker::Send` for `std::slice::Iter<'_, std::fmt::ArgumentV1<'_>>` = note: required because it appears within the type `std::fmt::Formatter<'_>` - = note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>` - = note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, impl std::future::Future, ()}]` +note: future is not `Send` as this value is used across an await + --> $DIR/async-fn-nonsend.rs:43:9 + | +LL | let f: &mut std::fmt::Formatter = panic!(); + | - has type `&mut std::fmt::Formatter<'_>` +LL | if non_sync().fmt(f).unwrap() == () { +LL | fut().await; + | ^^^^^^^^^^^ await occurs here, with `f` maybe used later +LL | } +LL | } + | - `f` is later dropped here = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, 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` diff --git a/src/test/ui/async-await/issue-64130-1-sync.stderr b/src/test/ui/async-await/issue-64130-1-sync.stderr index c20038dcb7921..9ce305864755c 100644 --- a/src/test/ui/async-await/issue-64130-1-sync.stderr +++ b/src/test/ui/async-await/issue-64130-1-sync.stderr @@ -1,15 +1,22 @@ -error[E0277]: `Foo` cannot be shared between threads safely +error[E0277]: future cannot be shared between threads safely --> $DIR/issue-64130-1-sync.rs:21:5 | LL | fn is_sync(t: T) { } | ------- ---- required by this bound in `is_sync` ... LL | is_sync(bar()); - | ^^^^^^^ `Foo` cannot be shared between threads safely + | ^^^^^^^ future is not `Sync` | = help: within `impl std::future::Future`, the trait `std::marker::Sync` is not implemented for `Foo` - = note: required because it appears within the type `{Foo, impl std::future::Future, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/issue-64130-1-sync.rs:13:16: 16:2 {Foo, impl std::future::Future, impl std::future::Future, ()}]` +note: future is not `Sync` as this value is used across an await + --> $DIR/issue-64130-1-sync.rs:15:5 + | +LL | let x = Foo; + | - has type `Foo` +LL | baz().await; + | ^^^^^^^^^^^ await occurs here, with `x` maybe used later +LL | } + | - `x` is later dropped here = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-1-sync.rs:13:16: 16:2 {Foo, impl std::future::Future, 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` diff --git a/src/test/ui/async-await/issue-64130-2-send.stderr b/src/test/ui/async-await/issue-64130-2-send.stderr index c4ef7713aec93..e29c929c76d92 100644 --- a/src/test/ui/async-await/issue-64130-2-send.stderr +++ b/src/test/ui/async-await/issue-64130-2-send.stderr @@ -1,15 +1,22 @@ -error[E0277]: `Foo` cannot be sent between threads safely +error[E0277]: future cannot be sent between threads safely --> $DIR/issue-64130-2-send.rs:21:5 | LL | fn is_send(t: T) { } | ------- ---- required by this bound in `is_send` ... LL | is_send(bar()); - | ^^^^^^^ `Foo` cannot be sent between threads safely + | ^^^^^^^ future is not `Send` | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `Foo` - = note: required because it appears within the type `{Foo, impl std::future::Future, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/issue-64130-2-send.rs:13:16: 16:2 {Foo, impl std::future::Future, impl std::future::Future, ()}]` +note: future is not `Send` as this value is used across an await + --> $DIR/issue-64130-2-send.rs:15:5 + | +LL | let x = Foo; + | - has type `Foo` +LL | baz().await; + | ^^^^^^^^^^^ await occurs here, with `x` maybe used later +LL | } + | - `x` is later dropped here = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-2-send.rs:13:16: 16:2 {Foo, impl std::future::Future, 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` diff --git a/src/test/ui/async-await/issue-64130-3-other.stderr b/src/test/ui/async-await/issue-64130-3-other.stderr index 6fe6a54919352..b0b8adfe47000 100644 --- a/src/test/ui/async-await/issue-64130-3-other.stderr +++ b/src/test/ui/async-await/issue-64130-3-other.stderr @@ -9,8 +9,15 @@ LL | is_qux(bar()); | = help: the following implementations were found: - = note: required because it appears within the type `{Foo, impl std::future::Future, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/issue-64130-3-other.rs:15:16: 18:2 {Foo, impl std::future::Future, impl std::future::Future, ()}]` +note: future does not implement `Qux` as this value is used across an await + --> $DIR/issue-64130-3-other.rs:17:5 + | +LL | let x = Foo; + | - has type `Foo` +LL | baz().await; + | ^^^^^^^^^^^ await occurs here, with `x` maybe used later +LL | } + | - `x` is later dropped here = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-3-other.rs:15:16: 18:2 {Foo, impl std::future::Future, 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` diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.stderr index fa244716a6863..ae1df2cb0c669 100644 --- a/src/test/ui/async-await/issue-64130-4-async-move.stderr +++ b/src/test/ui/async-await/issue-64130-4-async-move.stderr @@ -1,16 +1,24 @@ -error[E0277]: `(dyn std::any::Any + std::marker::Send + 'static)` cannot be shared between threads safely +error[E0277]: future cannot be sent between threads safely --> $DIR/issue-64130-4-async-move.rs:15:17 | LL | pub fn foo() -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^ `(dyn std::any::Any + std::marker::Send + 'static)` cannot be shared between threads safely + | ^^^^^^^^^^^^^^^^^^ future is not `Send` | = help: the trait `std::marker::Sync` is not implemented for `(dyn std::any::Any + std::marker::Send + 'static)` = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<(dyn std::any::Any + std::marker::Send + 'static)>` = note: required because it appears within the type `std::boxed::Box<(dyn std::any::Any + std::marker::Send + 'static)>` = note: required because it appears within the type `Client` - = note: required because of the requirements on the impl of `std::marker::Send` for `&Client` - = note: required because it appears within the type `for<'r> {&'r Client, Client, u16, u16, impl std::future::Future, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/issue-64130-4-async-move.rs:18:16: 25:6 client:Client for<'r> {&'r Client, Client, u16, u16, impl std::future::Future, impl std::future::Future, ()}]` +note: future is not `Send` as this value is used across an await + --> $DIR/issue-64130-4-async-move.rs:21:26 + | +LL | match client.status() { + | ------ has type `&Client` +LL | 200 => { +LL | let _x = get().await; + | ^^^^^^^^^^^ await occurs here, with `client` maybe used later +... +LL | } + | - `client` is later dropped here = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-4-async-move.rs:18:16: 25:6 client:Client for<'r> {&'r Client, Client, u16, u16, impl std::future::Future, impl std::future::Future, ()}]>` = note: required because it appears within the type `impl std::future::Future` = note: the return type of a function must have a statically known size diff --git a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr index 3facff778660c..dd296ba72e869 100644 --- a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr +++ b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr @@ -1,20 +1,32 @@ -error[E0277]: `std::sync::MutexGuard<'_, u32>` cannot be sent between threads safely +error[E0277]: future cannot be sent between threads safely --> $DIR/issue-64130-non-send-future-diags.rs:21:5 | LL | fn is_send(t: T) { } | ------- ---- required by this bound in `is_send` ... LL | is_send(foo()); - | ^^^^^^^ `std::sync::MutexGuard<'_, u32>` cannot be sent between threads safely + | ^^^^^^^ future is not `Send` | = 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, std::sync::MutexGuard<'s, u32>, impl std::future::Future, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/issue-64130-non-send-future-diags.rs:13:30: 16:2 x:&std::sync::Mutex for<'r, 's> {&'r std::sync::Mutex, std::sync::MutexGuard<'s, u32>, impl std::future::Future, impl std::future::Future, ()}]` +note: future is not `Send` as this value is used across an await + --> $DIR/issue-64130-non-send-future-diags.rs:15:5 + | +LL | let g = x.lock().unwrap(); + | - has type `std::sync::MutexGuard<'_, u32>` +LL | baz().await; + | ^^^^^^^^^^^ await occurs here, with `g` maybe used later +LL | } + | - `g` is later dropped here = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-non-send-future-diags.rs:13:30: 16:2 x:&std::sync::Mutex for<'r, 's> {&'r std::sync::Mutex, std::sync::MutexGuard<'s, u32>, impl std::future::Future, 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, 's, 't0, 't1> {u32, std::sync::Mutex, &'r std::sync::Mutex, &'s std::sync::Mutex, impl std::future::Future, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/issue-64130-non-send-future-diags.rs:9:16: 11:2 for<'r, 's, 't0, 't1> {u32, std::sync::Mutex, &'r std::sync::Mutex, &'s std::sync::Mutex, impl std::future::Future, impl std::future::Future, ()}]` +note: future is not `Send` as this value is used across an await + --> $DIR/issue-64130-non-send-future-diags.rs:10:5 + | +LL | bar(&Mutex::new(22)).await; + | --------------------^^^^^^- `bar(&Mutex::new(22))` is later dropped here + | | + | await occurs here, with `bar(&Mutex::new(22))` maybe used later + | has type `impl std::future::Future` = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-non-send-future-diags.rs:9:16: 11:2 for<'r, 's, 't0, 't1> {u32, std::sync::Mutex, &'r std::sync::Mutex, &'s std::sync::Mutex, impl std::future::Future, 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` diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr index 620db245d3e57..bd9475b29f98f 100644 --- a/src/test/ui/generator/not-send-sync.stderr +++ b/src/test/ui/generator/not-send-sync.stderr @@ -11,18 +11,25 @@ LL | assert_send(|| { = note: required because of the requirements on the impl of `std::marker::Send` for `&std::cell::Cell` = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:16:17: 20:6 a:&std::cell::Cell _]` -error[E0277]: `std::cell::Cell` cannot be shared between threads safely +error[E0277]: future cannot be shared between threads safely --> $DIR/not-send-sync.rs:9:5 | LL | fn assert_sync(_: T) {} | ----------- ---- required by this bound in `main::assert_sync` ... LL | assert_sync(|| { - | ^^^^^^^^^^^ `std::cell::Cell` cannot be shared between threads safely + | ^^^^^^^^^^^ future is not `Sync` | = help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell, ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell` - = note: required because it appears within the type `{std::cell::Cell, ()}` - = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell, ()}]` +note: future is not `Sync` as this value is used across an yield + --> $DIR/not-send-sync.rs:12:9 + | +LL | let a = Cell::new(2); + | - has type `std::cell::Cell` +LL | yield; + | ^^^^^ yield occurs here, with `a` maybe used later +LL | }); + | - `a` is later dropped here error: aborting due to 2 previous errors From da0d0533c25046d1159ffd10c5caf19a61b9128d Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 12 Dec 2019 17:53:14 -0500 Subject: [PATCH 6/9] Re-add 'gen_future' diagnostic item, fix more bugs --- src/librustc/traits/error_reporting.rs | 40 ++------------------------ src/libstd/future.rs | 1 + 2 files changed, 4 insertions(+), 37 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 367912a239334..77fb562991a48 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -2242,9 +2242,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ty::Adt(ty::AdtDef { did, .. }, ..) if self.tcx.is_diagnostic_item(sym::gen_future, *did) => {}, ty::Generator(did, ..) => { + generator = Some(did); debug!("note_obligation_cause_for_async_await: found generator {:?}", generator); - generator = Some(did); break; }, ty::GeneratorWitness(_) | ty::Opaque(..) => {}, @@ -2259,44 +2259,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // Now that we've found a generator, try to determine if we should // skip over any subsequence causes. while let Some(code) = next_code { - debug!("note_obligation_cause_for_async_await: code={:?}", code); - match code { - ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) | - ObligationCauseCode::ImplDerivedObligation(derived_obligation) => { - debug!("note_obligation_cause_for_async_await: self_ty.kind={:?}", - derived_obligation.parent_trait_ref.self_ty().kind); - - - match derived_obligation.parent_trait_ref.self_ty().kind { - ty::Adt(ty::AdtDef { did, .. }, ..) if - self.tcx.is_diagnostic_item(sym::gen_future, *did) => {}, - ty::Opaque(did, _) if - self.tcx.parent(did).map(|parent| { - self.tcx.is_diagnostic_item(sym::from_generator, parent) - }).unwrap_or(false) => {} - _ => break, - } - - next_code = Some(derived_obligation.parent_code.as_ref()); - next_predicate = Some( - self.resolve_vars_if_possible(&derived_obligation.parent_trait_ref) - .to_predicate() - ) - }, - _ => break - } - } - - - - // Now that we've found a generator, try to determine if we should - // skip over any subsequence causes. - while let Some(code) = next_code { - debug!("note_obligation_cause_for_async_await: code={:?}", code); + debug!("note_obligation_cause_for_async_await: inspecting code={:?}", code); match code { ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) | ObligationCauseCode::ImplDerivedObligation(derived_obligation) => { - debug!("note_obligation_cause_for_async_await: self_ty.kind={:?}", + debug!("note_obligation_cause_for_async_await: inspecting self_ty.kind={:?}", derived_obligation.parent_trait_ref.self_ty().kind); @@ -2320,7 +2287,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - let generator_did = generator.expect("can only reach this if there was a generator"); diff --git a/src/libstd/future.rs b/src/libstd/future.rs index 4385f2dde3553..d99d90a195a27 100644 --- a/src/libstd/future.rs +++ b/src/libstd/future.rs @@ -27,6 +27,7 @@ pub fn from_generator>(x: T) -> impl Future>(T); // We rely on the fact that async/await futures are immovable in order to create From 416d7d334509f2a28b4e20ca3de4698c34b1137b Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 12 Dec 2019 18:02:09 -0500 Subject: [PATCH 7/9] Update stderr, add new test --- .../ui/async-await/async-fn-nonsend.stderr | 8 ---- .../ui/async-await/issue-64130-1-sync.stderr | 2 - .../ui/async-await/issue-64130-2-send.stderr | 2 - .../ui/async-await/issue-64130-3-other.stderr | 2 - .../issue-64130-4-async-move.stderr | 2 - .../issue-64130-non-send-future-diags.stderr | 4 -- src/test/ui/async-await/nested-async-calls.rs | 28 +++++++++++++ .../ui/async-await/nested-async-calls.stderr | 42 +++++++++++++++++++ 8 files changed, 70 insertions(+), 20 deletions(-) create mode 100644 src/test/ui/async-await/nested-async-calls.rs create mode 100644 src/test/ui/async-await/nested-async-calls.stderr diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr index 43ea77c580b6f..bb3033210caa0 100644 --- a/src/test/ui/async-await/async-fn-nonsend.stderr +++ b/src/test/ui/async-await/async-fn-nonsend.stderr @@ -18,8 +18,6 @@ LL | fut().await; | ^^^^^^^^^^^ await occurs here, with `x` maybe used later LL | } | - `x` is later dropped here - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:21:39: 26:2 {impl std::fmt::Debug, impl std::future::Future, 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` error[E0277]: future cannot be sent between threads safely @@ -42,8 +40,6 @@ LL | Some(_) => fut().await, ... LL | } | - `non_send()` is later dropped here - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:28:40: 37:2 {impl std::fmt::Debug, std::option::Option, impl std::future::Future, 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` error[E0277]: future cannot be sent between threads safely @@ -69,8 +65,6 @@ LL | fut().await; LL | } LL | } | - `f` is later dropped here - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, 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` error[E0277]: future cannot be sent between threads safely @@ -100,8 +94,6 @@ LL | fut().await; LL | } LL | } | - `f` is later dropped here - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, 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` error: aborting due to 4 previous errors diff --git a/src/test/ui/async-await/issue-64130-1-sync.stderr b/src/test/ui/async-await/issue-64130-1-sync.stderr index 9ce305864755c..cb5fcd0db2ee5 100644 --- a/src/test/ui/async-await/issue-64130-1-sync.stderr +++ b/src/test/ui/async-await/issue-64130-1-sync.stderr @@ -17,8 +17,6 @@ LL | baz().await; | ^^^^^^^^^^^ await occurs here, with `x` maybe used later LL | } | - `x` is later dropped here - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-1-sync.rs:13:16: 16:2 {Foo, impl std::future::Future, 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` error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-64130-2-send.stderr b/src/test/ui/async-await/issue-64130-2-send.stderr index e29c929c76d92..390c55bb0cc77 100644 --- a/src/test/ui/async-await/issue-64130-2-send.stderr +++ b/src/test/ui/async-await/issue-64130-2-send.stderr @@ -17,8 +17,6 @@ LL | baz().await; | ^^^^^^^^^^^ await occurs here, with `x` maybe used later LL | } | - `x` is later dropped here - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-2-send.rs:13:16: 16:2 {Foo, impl std::future::Future, 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` error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-64130-3-other.stderr b/src/test/ui/async-await/issue-64130-3-other.stderr index b0b8adfe47000..d95703462be60 100644 --- a/src/test/ui/async-await/issue-64130-3-other.stderr +++ b/src/test/ui/async-await/issue-64130-3-other.stderr @@ -18,8 +18,6 @@ LL | baz().await; | ^^^^^^^^^^^ await occurs here, with `x` maybe used later LL | } | - `x` is later dropped here - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-3-other.rs:15:16: 18:2 {Foo, impl std::future::Future, 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` error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.stderr index ae1df2cb0c669..51d7b757a615d 100644 --- a/src/test/ui/async-await/issue-64130-4-async-move.stderr +++ b/src/test/ui/async-await/issue-64130-4-async-move.stderr @@ -19,8 +19,6 @@ LL | let _x = get().await; ... LL | } | - `client` is later dropped here - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-4-async-move.rs:18:16: 25:6 client:Client for<'r> {&'r Client, Client, u16, u16, impl std::future::Future, impl std::future::Future, ()}]>` - = note: required because it appears within the type `impl std::future::Future` = note: the return type of a function must have a statically known size error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr index dd296ba72e869..c0a6a5043940a 100644 --- a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr +++ b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr @@ -17,8 +17,6 @@ LL | baz().await; | ^^^^^^^^^^^ await occurs here, with `g` maybe used later LL | } | - `g` is later dropped here - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-non-send-future-diags.rs:13:30: 16:2 x:&std::sync::Mutex for<'r, 's> {&'r std::sync::Mutex, std::sync::MutexGuard<'s, u32>, impl std::future::Future, impl std::future::Future, ()}]>` - = note: required because it appears within the type `impl std::future::Future` note: future is not `Send` as this value is used across an await --> $DIR/issue-64130-non-send-future-diags.rs:10:5 | @@ -27,8 +25,6 @@ LL | bar(&Mutex::new(22)).await; | | | await occurs here, with `bar(&Mutex::new(22))` maybe used later | has type `impl std::future::Future` - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/issue-64130-non-send-future-diags.rs:9:16: 11:2 for<'r, 's, 't0, 't1> {u32, std::sync::Mutex, &'r std::sync::Mutex, &'s std::sync::Mutex, impl std::future::Future, 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` error: aborting due to previous error diff --git a/src/test/ui/async-await/nested-async-calls.rs b/src/test/ui/async-await/nested-async-calls.rs new file mode 100644 index 0000000000000..1c4ca5ac765c5 --- /dev/null +++ b/src/test/ui/async-await/nested-async-calls.rs @@ -0,0 +1,28 @@ +// edition:2018 + +async fn first() { + second().await; +} + +async fn second() { + third().await; +} + +async fn third() { + struct NotSend(*const ()); + struct Outer(NotSend); + async fn dummy() {} + + let _a: Outer; + dummy().await; +} + +fn require_send(_val: T) {} + +fn main() { + struct Wrapper(T); + let wrapped = Wrapper(first()); + + require_send(wrapped); + //~^ ERROR future cannot be sent between threads safely +} diff --git a/src/test/ui/async-await/nested-async-calls.stderr b/src/test/ui/async-await/nested-async-calls.stderr new file mode 100644 index 0000000000000..7291cd2cce1d2 --- /dev/null +++ b/src/test/ui/async-await/nested-async-calls.stderr @@ -0,0 +1,42 @@ +error[E0277]: future cannot be sent between threads safely + --> $DIR/nested-async-calls.rs:26:5 + | +LL | fn require_send(_val: T) {} + | ------------ ---- required by this bound in `require_send` +... +LL | require_send(wrapped); + | ^^^^^^^^^^^^ future is not `Send` + | + = help: within `main::Wrapper`, the trait `std::marker::Send` is not implemented for `*const ()` + = note: required because it appears within the type `third::{{closure}}#0::NotSend` +note: future is not `Send` as this value is used across an await + --> $DIR/nested-async-calls.rs:17:5 + | +LL | let _a: Outer; + | -- has type `third::{{closure}}#0::Outer` +LL | dummy().await; + | ^^^^^^^^^^^^^ await occurs here, with `_a` maybe used later +LL | } + | - `_a` is later dropped here +note: future is not `Send` as this value is used across an await + --> $DIR/nested-async-calls.rs:8:5 + | +LL | third().await; + | -------^^^^^^- `third()` is later dropped here + | | + | await occurs here, with `third()` maybe used later + | has type `impl std::future::Future` +note: future is not `Send` as this value is used across an await + --> $DIR/nested-async-calls.rs:4:5 + | +LL | second().await; + | --------^^^^^^- `second()` is later dropped here + | | + | await occurs here, with `second()` maybe used later + | has 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 `main::Wrapper` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 10a763371f5f14793a6bdb2bf10fce29848d85ed Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 12 Dec 2019 18:18:55 -0500 Subject: [PATCH 8/9] Some cleanup --- src/librustc/traits/error_reporting.rs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 77fb562991a48..c413a0529d1e8 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -2176,19 +2176,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { trait_predicate: &TraitPredicate<'tcx>, code: &ObligationCauseCode<'tcx>, ) -> bool { - /*debug!("note_obligation_cause_for_async_await: obligation.predicate={:?} \ - obligation.cause.span={:?}", obligation.predicate, obligation.cause.span);*/ + debug!("note_obligation_cause_for_async_await: trait_predicate={:?} \ + code={:?}", trait_predicate, code); let source_map = self.tcx.sess.source_map(); - // Look into the obligation predicate to determine the type in the generator which meant - // that the predicate was not satisifed. - /*let (trait_ref, target_ty) = match obligation.predicate { - ty::Predicate::Trait(trait_predicate) => - (trait_predicate.skip_binder().trait_ref, trait_predicate.skip_binder().self_ty()), - _ => return false, - };*/ - - let (mut trait_ref, mut target_ty) = (trait_predicate.trait_ref, trait_predicate.self_ty()); + let (trait_ref, target_ty) = (trait_predicate.trait_ref, trait_predicate.self_ty()); debug!("note_obligation_cause_for_async_await: target_ty={:?}", target_ty); From 25c30357d45435fae58ebcb50426682658617818 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 12 Dec 2019 18:50:34 -0500 Subject: [PATCH 9/9] Fix 'last_generator' error messages --- src/librustc/traits/error_reporting.rs | 23 ++++++++++++++++++- .../ui/async-await/async-fn-nonsend.stderr | 8 +++---- .../ui/async-await/issue-64130-1-sync.stderr | 2 +- .../ui/async-await/issue-64130-2-send.stderr | 2 +- .../issue-64130-4-async-move.stderr | 2 +- .../issue-64130-non-send-future-diags.stderr | 2 +- .../ui/async-await/nested-async-calls.stderr | 2 +- src/test/ui/generator/not-send-sync.stderr | 2 +- 8 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index c413a0529d1e8..3bb83eabc8da7 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -2210,7 +2210,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // the type. The last generator has information about where the bound was introduced. At // least one generator should be present for this diagnostic to be modified. let mut generator = None; - let mut last_generator = None; let mut next_code = Some(code); let mut next_predicate = None; @@ -2281,6 +2280,28 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let generator_did = generator.expect("can only reach this if there was a generator"); + // Finally, see if there are any generator types remaining in the 'error stack'. + // If there aren't, then treat the current generator as the 'last generator', + // which will make `note_obligation_cause_for_async_await` emit an extra + // message for it + let mut target_code = next_code; + let mut last_generator = Some(generator_did); + while let Some(code) = target_code { + debug!("note_obligation_cause_for_async_await: last_generator code={:?}", code); + if let ObligationCauseCode::BuiltinDerivedObligation(obligation) | + ObligationCauseCode::ImplDerivedObligation(obligation) = code { + if let ty::Generator(..) = obligation.parent_trait_ref.self_ty().kind { + // We found another generator, so our current generator can't be + // the last one + last_generator = None; + break; + } + target_code = Some(obligation.parent_code.as_ref()); + } else { + break; + } + } + let span = self.tcx.def_span(generator_did); diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr index bb3033210caa0..bc86a55056de8 100644 --- a/src/test/ui/async-await/async-fn-nonsend.stderr +++ b/src/test/ui/async-await/async-fn-nonsend.stderr @@ -5,7 +5,7 @@ LL | fn assert_send(_: impl Send) {} | ----------- ---- required by this bound in `assert_send` ... LL | assert_send(local_dropped_before_await()); - | ^^^^^^^^^^^ future is not `Send` + | ^^^^^^^^^^^ future returned by `local_dropped_before_await` is not `Send` | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>` note: future is not `Send` as this value is used across an await @@ -27,7 +27,7 @@ LL | fn assert_send(_: impl Send) {} | ----------- ---- required by this bound in `assert_send` ... LL | assert_send(non_send_temporary_in_match()); - | ^^^^^^^^^^^ future is not `Send` + | ^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send` | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>` note: future is not `Send` as this value is used across an await @@ -49,7 +49,7 @@ LL | fn assert_send(_: impl Send) {} | ----------- ---- required by this bound in `assert_send` ... LL | assert_send(non_sync_with_method_call()); - | ^^^^^^^^^^^ future is not `Send` + | ^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send` | = help: the trait `std::marker::Send` is not implemented for `dyn std::fmt::Write` = note: required because of the requirements on the impl of `std::marker::Send` for `&mut dyn std::fmt::Write` @@ -74,7 +74,7 @@ LL | fn assert_send(_: impl Send) {} | ----------- ---- required by this bound in `assert_send` ... LL | assert_send(non_sync_with_method_call()); - | ^^^^^^^^^^^ future is not `Send` + | ^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send` | = help: within `std::fmt::ArgumentV1<'_>`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)` = note: required because it appears within the type `std::marker::PhantomData<*mut (dyn std::ops::Fn() + 'static)>` diff --git a/src/test/ui/async-await/issue-64130-1-sync.stderr b/src/test/ui/async-await/issue-64130-1-sync.stderr index cb5fcd0db2ee5..3375b095b4e46 100644 --- a/src/test/ui/async-await/issue-64130-1-sync.stderr +++ b/src/test/ui/async-await/issue-64130-1-sync.stderr @@ -5,7 +5,7 @@ LL | fn is_sync(t: T) { } | ------- ---- required by this bound in `is_sync` ... LL | is_sync(bar()); - | ^^^^^^^ future is not `Sync` + | ^^^^^^^ future returned by `bar` is not `Sync` | = help: within `impl std::future::Future`, the trait `std::marker::Sync` is not implemented for `Foo` note: future is not `Sync` as this value is used across an await diff --git a/src/test/ui/async-await/issue-64130-2-send.stderr b/src/test/ui/async-await/issue-64130-2-send.stderr index 390c55bb0cc77..c5f71c3d48012 100644 --- a/src/test/ui/async-await/issue-64130-2-send.stderr +++ b/src/test/ui/async-await/issue-64130-2-send.stderr @@ -5,7 +5,7 @@ LL | fn is_send(t: T) { } | ------- ---- required by this bound in `is_send` ... LL | is_send(bar()); - | ^^^^^^^ future is not `Send` + | ^^^^^^^ future returned by `bar` is not `Send` | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `Foo` note: future is not `Send` as this value is used across an await diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.stderr index 51d7b757a615d..a8b6876f0522d 100644 --- a/src/test/ui/async-await/issue-64130-4-async-move.stderr +++ b/src/test/ui/async-await/issue-64130-4-async-move.stderr @@ -2,7 +2,7 @@ error[E0277]: future cannot be sent between threads safely --> $DIR/issue-64130-4-async-move.rs:15:17 | LL | pub fn foo() -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^ future is not `Send` + | ^^^^^^^^^^^^^^^^^^ future returned by `foo` is not `Send` | = help: the trait `std::marker::Sync` is not implemented for `(dyn std::any::Any + std::marker::Send + 'static)` = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<(dyn std::any::Any + std::marker::Send + 'static)>` diff --git a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr index c0a6a5043940a..4652eb7924ade 100644 --- a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr +++ b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr @@ -5,7 +5,7 @@ LL | fn is_send(t: T) { } | ------- ---- required by this bound in `is_send` ... LL | is_send(foo()); - | ^^^^^^^ future is not `Send` + | ^^^^^^^ future returned by `foo` is not `Send` | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::sync::MutexGuard<'_, u32>` note: future is not `Send` as this value is used across an await diff --git a/src/test/ui/async-await/nested-async-calls.stderr b/src/test/ui/async-await/nested-async-calls.stderr index 7291cd2cce1d2..000fd7706d145 100644 --- a/src/test/ui/async-await/nested-async-calls.stderr +++ b/src/test/ui/async-await/nested-async-calls.stderr @@ -5,7 +5,7 @@ LL | fn require_send(_val: T) {} | ------------ ---- required by this bound in `require_send` ... LL | require_send(wrapped); - | ^^^^^^^^^^^^ future is not `Send` + | ^^^^^^^^^^^^ future returned by `first` is not `Send` | = help: within `main::Wrapper`, the trait `std::marker::Send` is not implemented for `*const ()` = note: required because it appears within the type `third::{{closure}}#0::NotSend` diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr index bd9475b29f98f..aa7fe971f13d9 100644 --- a/src/test/ui/generator/not-send-sync.stderr +++ b/src/test/ui/generator/not-send-sync.stderr @@ -18,7 +18,7 @@ LL | fn assert_sync(_: T) {} | ----------- ---- required by this bound in `main::assert_sync` ... LL | assert_sync(|| { - | ^^^^^^^^^^^ future is not `Sync` + | ^^^^^^^^^^^ future returned by `main` is not `Sync` | = help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell, ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell` note: future is not `Sync` as this value is used across an yield