From 00d12ef9016f2eab194488ac7d51567175eddebc Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 16 Apr 2020 23:14:11 +0800 Subject: [PATCH] add test for correct await span --- src/librustc_middle/ty/context.rs | 4 ++-- .../traits/error_reporting/suggestions.rs | 24 ++++++++++++------- .../check/generator_interior.rs | 2 +- src/test/ui/async-await/issue-71137.rs | 21 ++++++++++++++++ src/test/ui/async-await/issue-71137.stderr | 23 ++++++++++++++++++ 5 files changed, 62 insertions(+), 12 deletions(-) create mode 100644 src/test/ui/async-await/issue-71137.rs create mode 100644 src/test/ui/async-await/issue-71137.stderr diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index e127c222dac..c6228a913cf 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -314,8 +314,8 @@ pub struct GeneratorInteriorTypeCause<'tcx> { pub span: Span, /// Span of the scope of the captured binding. pub scope_span: Option, - /// Span of `.await` statement. - pub await_span: Span, + /// Span of `.await` or `yield` expression. + pub yield_span: Span, /// Expr which the type evaluated from. pub expr: Option, } diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index c0e14d044ec..51ac552c312 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -1261,13 +1261,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ty_matches(ty) }) .map(|expr| expr.span); - let ty::GeneratorInteriorTypeCause { span, scope_span, await_span, expr, .. } = + let ty::GeneratorInteriorTypeCause { span, scope_span, yield_span, expr, .. } = cause; ( span, source_map.span_to_snippet(*span), scope_span, - await_span, + yield_span, expr, from_awaited_ty, ) @@ -1275,17 +1275,17 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { debug!( "maybe_note_obligation_cause_for_async_await: target_ty={:?} \ - generator_interior_types={:?} target_span={:?} await_span={:?}", - target_ty, tables.generator_interior_types, target_span, await_span + generator_interior_types={:?} target_span={:?}", + target_ty, tables.generator_interior_types, target_span ); - if let Some((target_span, Ok(snippet), scope_span, await_span, expr, from_awaited_ty)) = + if let Some((target_span, Ok(snippet), scope_span, yield_span, expr, from_awaited_ty)) = target_span { self.note_obligation_cause_for_async_await( err, *target_span, scope_span, - await_span, + *yield_span, *expr, snippet, generator_body, @@ -1310,7 +1310,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err: &mut DiagnosticBuilder<'_>, target_span: Span, scope_span: &Option, - await_span: Span, + yield_span: Span, expr: Option, snippet: String, inner_generator_body: Option<&hir::Body<'_>>, @@ -1386,6 +1386,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { if let Some(await_span) = from_awaited_ty { // The type causing this obligation is one being awaited at await_span. let mut span = MultiSpan::from_span(await_span); + + span.push_span_label( + await_span, + format!("await occurs here on type `{}`, which {}", target_ty, trait_explanation), + ); + err.span_note( span, &format!( @@ -1399,9 +1405,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { "note_obligation_cause_for_async_await generator_interior_types: {:#?}", tables.generator_interior_types ); - let mut span = MultiSpan::from_span(await_span); + let mut span = MultiSpan::from_span(yield_span); span.push_span_label( - await_span, + yield_span, format!("{} occurs here, with `{}` maybe used later", await_or_yield, snippet), ); diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index 99e01a0332f..716d23b4d17 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -96,7 +96,7 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> { span: source_span, ty: &ty, scope_span, - await_span: yield_data.span, + yield_span: yield_data.span, expr: expr.map(|e| e.hir_id), }) .or_insert(entries); diff --git a/src/test/ui/async-await/issue-71137.rs b/src/test/ui/async-await/issue-71137.rs new file mode 100644 index 00000000000..ebb392a4530 --- /dev/null +++ b/src/test/ui/async-await/issue-71137.rs @@ -0,0 +1,21 @@ +// edition:2018 + +use std::future::Future; +use std::sync::Mutex; + +fn fake_spawn(f: F) { } + +async fn wrong_mutex() { + let m = Mutex::new(1); + { + let mut guard = m.lock().unwrap(); + (async { "right"; }).await; + *guard += 1; + } + + (async { "wrong"; }).await; +} + +fn main() { + fake_spawn(wrong_mutex()); //~ Error future cannot be sent between threads safely +} diff --git a/src/test/ui/async-await/issue-71137.stderr b/src/test/ui/async-await/issue-71137.stderr new file mode 100644 index 00000000000..788a9bc2c7e --- /dev/null +++ b/src/test/ui/async-await/issue-71137.stderr @@ -0,0 +1,23 @@ +error: future cannot be sent between threads safely + --> $DIR/issue-71137.rs:20:3 + | +LL | fn fake_spawn(f: F) { } + | ---- required by this bound in `fake_spawn` +... +LL | fake_spawn(wrong_mutex()); + | ^^^^^^^^^^ future returned by `wrong_mutex` is not `Send` + | + = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::sync::MutexGuard<'_, i32>` +note: future is not `Send` as this value is used across an await + --> $DIR/issue-71137.rs:12:5 + | +LL | let mut guard = m.lock().unwrap(); + | --------- has type `std::sync::MutexGuard<'_, i32>` which is not `Send` +LL | (async { "right"; }).await; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ await occurs here, with `mut guard` maybe used later +LL | *guard += 1; +LL | } + | - `mut guard` is later dropped here + +error: aborting due to previous error +