about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/hir/mod.rs4
-rw-r--r--src/librustc_mir/borrow_check/conflict_errors.rs30
-rw-r--r--src/librustc_mir/borrow_check/error_reporting.rs45
-rw-r--r--src/test/ui/async-await/async-borrowck-escaping-block-error.stderr2
4 files changed, 55 insertions, 26 deletions
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index e72f46682ce..7350f89018b 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1366,6 +1366,10 @@ impl Body {
             hir_id: self.value.hir_id,
         }
     }
+
+    pub fn generator_kind(&self) -> Option<GeneratorKind> {
+        self.generator_kind
+    }
 }
 
 /// The type of source expression that caused this generator to be created.
diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs
index 2f9df7bd77e..098258994f4 100644
--- a/src/librustc_mir/borrow_check/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/conflict_errors.rs
@@ -1,5 +1,6 @@
 use rustc::hir;
 use rustc::hir::def_id::DefId;
+use rustc::hir::{AsyncGeneratorKind, GeneratorKind};
 use rustc::mir::{
     self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory, Local,
     LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, PlaceRef, ProjectionElem, Rvalue,
@@ -788,7 +789,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     ..
                 },
             ) if borrow_spans.for_closure() => self.report_escaping_closure_capture(
-                borrow_spans.args_or_use(),
+                borrow_spans,
                 borrow_span,
                 region_name,
                 category,
@@ -806,7 +807,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 },
 
             ) if borrow_spans.for_generator() => self.report_escaping_closure_capture(
-                borrow_spans.args_or_use(),
+                borrow_spans,
                 borrow_span,
                 region_name,
                 category,
@@ -1195,7 +1196,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
     fn report_escaping_closure_capture(
         &mut self,
-        args_span: Span,
+        use_span: UseSpans,
         var_span: Span,
         fr_name: &RegionName,
         category: ConstraintCategory,
@@ -1203,7 +1204,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         captured_var: &str,
     ) -> DiagnosticBuilder<'cx> {
         let tcx = self.infcx.tcx;
-
+        let args_span = use_span.args_or_use();
         let mut err = self.cannot_capture_in_long_lived_closure(
             args_span,
             captured_var,
@@ -1223,12 +1224,25 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             },
             Err(_) => "move |<args>| <body>".to_string()
         };
-
+        let kind = match use_span.generator_kind() {
+            Some(generator_kind) => match generator_kind {
+                GeneratorKind::Async(async_kind) => match async_kind {
+                    AsyncGeneratorKind::Block => "async block",
+                    AsyncGeneratorKind::Closure => "async closure",
+                    _ => bug!("async block/closure expected, but async funtion found."),
+                },
+                GeneratorKind::Gen => "generator",
+            }
+            None => "closure",
+        };
         err.span_suggestion(
             args_span,
-            &format!("to force the closure to take ownership of {} (and any \
-                      other referenced variables), use the `move` keyword",
-                      captured_var),
+            &format!(
+                "to force the {} to take ownership of {} (and any \
+                 other referenced variables), use the `move` keyword",
+                 kind,
+                 captured_var
+            ),
             suggestion,
             Applicability::MachineApplicable,
         );
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index dc7e4b22065..5e0727d5157 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -1,6 +1,7 @@
 use rustc::hir;
 use rustc::hir::def::Namespace;
 use rustc::hir::def_id::DefId;
+use rustc::hir::GeneratorKind;
 use rustc::mir::{
     AggregateKind, Constant, Field, Local, LocalKind, Location, Operand,
     Place, PlaceBase, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind,
@@ -14,7 +15,7 @@ use syntax_pos::Span;
 use syntax::symbol::sym;
 
 use super::borrow_set::BorrowData;
-use super::{MirBorrowckCtxt};
+use super::MirBorrowckCtxt;
 use crate::dataflow::move_paths::{InitLocation, LookupResult};
 
 pub(super) struct IncludingDowncast(pub(super) bool);
@@ -604,7 +605,7 @@ pub(super) enum UseSpans {
     // The access is caused by capturing a variable for a closure.
     ClosureUse {
         // This is true if the captured variable was from a generator.
-        is_generator: bool,
+        generator_kind: Option<GeneratorKind>,
         // The span of the args of the closure, including the `move` keyword if
         // it's present.
         args_span: Span,
@@ -631,6 +632,13 @@ impl UseSpans {
         }
     }
 
+    pub(super) fn generator_kind(self) -> Option<GeneratorKind> {
+        match self {
+            UseSpans::ClosureUse { generator_kind, .. } => generator_kind,
+            _ => None,
+        }
+    }
+
     // Add a span label to the arguments of the closure, if it exists.
     pub(super) fn args_span_label(
         self,
@@ -656,7 +664,7 @@ impl UseSpans {
     /// Returns `false` if this place is not used in a closure.
     pub(super) fn for_closure(&self) -> bool {
         match *self {
-            UseSpans::ClosureUse { is_generator, .. } => !is_generator,
+            UseSpans::ClosureUse { generator_kind, .. } => generator_kind.is_none(),
             _ => false,
         }
     }
@@ -664,7 +672,7 @@ impl UseSpans {
     /// Returns `false` if this place is not used in a generator.
     pub(super) fn for_generator(&self) -> bool {
         match *self {
-            UseSpans::ClosureUse { is_generator, .. } => is_generator,
+            UseSpans::ClosureUse { generator_kind, .. } => generator_kind.is_some(),
             _ => false,
         }
     }
@@ -672,7 +680,7 @@ impl UseSpans {
     /// Describe the span associated with a use of a place.
     pub(super) fn describe(&self) -> String {
         match *self {
-            UseSpans::ClosureUse { is_generator, .. } => if is_generator {
+            UseSpans::ClosureUse { generator_kind, .. } => if generator_kind.is_some() {
                 " in generator".to_string()
             } else {
                 " in closure".to_string()
@@ -794,19 +802,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         if let  StatementKind::Assign(
             box(_, Rvalue::Aggregate(ref kind, ref places))
         ) = stmt.kind {
-            let (def_id, is_generator) = match kind {
-                box AggregateKind::Closure(def_id, _) => (def_id, false),
-                box AggregateKind::Generator(def_id, _, _) => (def_id, true),
+            let def_id = match kind {
+                box AggregateKind::Closure(def_id, _)
+                | box AggregateKind::Generator(def_id, _, _) => def_id,
                 _ => return OtherUse(stmt.source_info.span),
             };
 
             debug!(
-                "move_spans: def_id={:?} is_generator={:?} places={:?}",
-                def_id, is_generator, places
+                "move_spans: def_id={:?} places={:?}",
+                def_id, places
             );
-            if let Some((args_span, var_span)) = self.closure_span(*def_id, moved_place, places) {
+            if let Some((args_span, generator_kind, var_span))
+                = self.closure_span(*def_id, moved_place, places) {
                 return ClosureUse {
-                    is_generator,
+                    generator_kind,
                     args_span,
                     var_span,
                 };
@@ -857,11 +866,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     "borrow_spans: def_id={:?} is_generator={:?} places={:?}",
                     def_id, is_generator, places
                 );
-                if let Some((args_span, var_span)) = self.closure_span(
+                if let Some((args_span, generator_kind, var_span)) = self.closure_span(
                     *def_id, Place::from(target).as_ref(), places
                 ) {
                     return ClosureUse {
-                        is_generator,
+                        generator_kind,
                         args_span,
                         var_span,
                     };
@@ -884,7 +893,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         def_id: DefId,
         target_place: PlaceRef<'cx, 'tcx>,
         places: &Vec<Operand<'tcx>>,
-    ) -> Option<(Span, Span)> {
+    ) -> Option<(Span, Option<GeneratorKind>, Span)> {
         debug!(
             "closure_span: def_id={:?} target_place={:?} places={:?}",
             def_id, target_place, places
@@ -893,14 +902,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind;
         debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
         if let hir::ExprKind::Closure(
-            .., args_span, _
+            .., body_id, args_span, _
         ) = expr {
             for (upvar, place) in self.infcx.tcx.upvars(def_id)?.values().zip(places) {
                 match place {
                     Operand::Copy(place) |
                     Operand::Move(place) if target_place == place.as_ref() => {
                         debug!("closure_span: found captured local {:?}", place);
-                        return Some((*args_span, upvar.span));
+                        let body = self.infcx.tcx.hir().body(*body_id);
+                        let generator_kind = body.generator_kind();
+                        return Some((*args_span, generator_kind, upvar.span));
                     },
                     _ => {}
                 }
diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr
index af17ecc86fb..0eb3971d14a 100644
--- a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr
+++ b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr
@@ -12,7 +12,7 @@ note: generator is returned here
    |
 LL | fn foo() -> Box<impl std::future::Future<Output = u32>> {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+help: to force the async block to take ownership of `x` (and any other referenced variables), use the `move` keyword
    |
 LL |     Box::new(async move { x } )
    |                    ^^^^^^^^^^