From fe5b9c140932b7ce7aa0f84ba6f07dbbe379f699 Mon Sep 17 00:00:00 2001 From: Roxane Date: Sun, 4 Oct 2020 15:48:37 -0400 Subject: [PATCH] Fix failing test --- .../src/traits/error_reporting/suggestions.rs | 20 +++++++++++++++++++ src/test/ui/async-await/issue-70818.stderr | 17 ++++++---------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 90a8d9634ae1e..dfff1fd2bedce 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1307,6 +1307,26 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let mut generator = None; let mut outer_generator = None; let mut next_code = Some(&obligation.cause.code); + // By introducing a tuple into the upvar types, the first item in the obligation chain + // can be of Tuple type instead of the generator that captured the type. We want to catch for + // this case and skip it. + if let Some(code) = next_code { + match code { + ObligationCauseCode::DerivedObligation(derived_obligation) + | ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) + | ObligationCauseCode::ImplDerivedObligation(derived_obligation) => { + let ty = derived_obligation.parent_trait_ref.skip_binder().self_ty(); + match *ty.kind() { + ty::Tuple(_) => { + next_code = Some(derived_obligation.parent_code.as_ref()); + } + _ => {} + } + } + _ => {} + } + } + while let Some(code) = next_code { debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code); match code { diff --git a/src/test/ui/async-await/issue-70818.stderr b/src/test/ui/async-await/issue-70818.stderr index f36106c076171..364194bea100e 100644 --- a/src/test/ui/async-await/issue-70818.stderr +++ b/src/test/ui/async-await/issue-70818.stderr @@ -1,21 +1,17 @@ -error[E0277]: `U` cannot be sent between threads safely +error: future cannot be sent between threads safely --> $DIR/issue-70818.rs:4:38 | LL | fn foo(ty: T, ty1: U) -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `U` cannot be sent between threads safely + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` LL | LL | async { (ty, ty1) } | ------------------- this returned value is of type `impl Future` - | - ::: $SRC_DIR/core/src/future/mod.rs:LL:COL | -LL | pub const fn from_generator(gen: T) -> impl Future - | ------------------------------- within this `impl Future` +note: captured value is not `Send` + --> $DIR/issue-70818.rs:6:18 | - = note: required because it appears within the type `(T, U)` - = note: required because it appears within the type `[static generator@$DIR/issue-70818.rs:6:11: 6:24 _]` - = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-70818.rs:6:11: 6:24 _]>` - = note: required because it appears within the type `impl Future` +LL | async { (ty, ty1) } + | ^^^ has type `U` which is not `Send` = note: the return type of a function must have a statically known size help: consider restricting type parameter `U` | @@ -24,4 +20,3 @@ LL | fn foo(ty: T, ty1: U) -> impl Future + S error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`.