about summary refs log tree commit diff
path: root/compiler/rustc_borrowck/src/diagnostics
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-01-07 20:43:22 +0100
committerGitHub <noreply@github.com>2023-01-07 20:43:22 +0100
commit1e6710da59f8b801bf89641bfcb7795dd6d61ae8 (patch)
tree4738486c1a4717ca564292eeebdbe249f65d95f6 /compiler/rustc_borrowck/src/diagnostics
parent0c8d11b97ce209ce9cda03c0a146d7224aaa7ce7 (diff)
parentce6b7179afcdf6ae2dad7e69c56f1f5c957b47bd (diff)
downloadrust-1e6710da59f8b801bf89641bfcb7795dd6d61ae8.tar.gz
rust-1e6710da59f8b801bf89641bfcb7795dd6d61ae8.zip
Rollup merge of #106509 - estebank:closure-in-block, r=davidtwco
Detect closures assigned to binding in block

Fix #58497.
Diffstat (limited to 'compiler/rustc_borrowck/src/diagnostics')
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs31
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs12
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs2
3 files changed, 38 insertions, 7 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 492c8d02012..d99bfc01a42 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1425,6 +1425,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             // and `move` will not help here.
             (
                 Some(name),
+                BorrowExplanation::UsedLater(LaterUseKind::ClosureCapture, var_or_use_span, _),
+            ) => self.report_escaping_closure_capture(
+                borrow_spans,
+                borrow_span,
+                &RegionName {
+                    name: self.synthesize_region_name(),
+                    source: RegionNameSource::Static,
+                },
+                ConstraintCategory::CallArgument(None),
+                var_or_use_span,
+                &format!("`{}`", name),
+                "block",
+            ),
+            (
+                Some(name),
                 BorrowExplanation::MustBeValidFor {
                     category:
                         category @ (ConstraintCategory::Return(_)
@@ -1443,6 +1458,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     category,
                     span,
                     &format!("`{}`", name),
+                    "function",
                 ),
             (
                 name,
@@ -1895,6 +1911,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         Some(err)
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn report_escaping_closure_capture(
         &mut self,
         use_span: UseSpans<'tcx>,
@@ -1903,6 +1920,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         category: ConstraintCategory<'tcx>,
         constraint_span: Span,
         captured_var: &str,
+        scope: &str,
     ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
         let tcx = self.infcx.tcx;
         let args_span = use_span.args_or_use();
@@ -1933,8 +1951,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             None => "closure",
         };
 
-        let mut err =
-            self.cannot_capture_in_long_lived_closure(args_span, kind, captured_var, var_span);
+        let mut err = self.cannot_capture_in_long_lived_closure(
+            args_span,
+            kind,
+            captured_var,
+            var_span,
+            scope,
+        );
         err.span_suggestion_verbose(
             sugg_span,
             &format!(
@@ -1956,10 +1979,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 if matches!(use_span.generator_kind(), Some(GeneratorKind::Async(_))) {
                     err.note(
                         "async blocks are not executed immediately and must either take a \
-                    reference or ownership of outside variables they use",
+                         reference or ownership of outside variables they use",
                     );
                 } else {
-                    let msg = format!("function requires argument type to outlive `{}`", fr_name);
+                    let msg = format!("{scope} requires argument type to outlive `{fr_name}`");
                     err.span_note(constraint_span, &msg);
                 }
             }
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 00f5e8a8397..c4ae30151c4 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -444,6 +444,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// First span returned points to the location of the conflicting use
     /// Second span if `Some` is returned in the case of closures and points
     /// to the use of the path
+    #[instrument(level = "debug", skip(self))]
     fn later_use_kind(
         &self,
         borrow: &BorrowData<'tcx>,
@@ -461,11 +462,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 let block = &self.body.basic_blocks[location.block];
 
                 let kind = if let Some(&Statement {
-                    kind: StatementKind::FakeRead(box (FakeReadCause::ForLet(_), _)),
+                    kind: StatementKind::FakeRead(box (FakeReadCause::ForLet(_), place)),
                     ..
                 }) = block.statements.get(location.statement_index)
                 {
-                    LaterUseKind::FakeLetRead
+                    if let Some(l) = place.as_local()
+                        && let local_decl = &self.body.local_decls[l]
+                        && local_decl.ty.is_closure()
+                    {
+                        LaterUseKind::ClosureCapture
+                    } else {
+                        LaterUseKind::FakeLetRead
+                    }
                 } else if self.was_captured_by_trait_object(borrow) {
                     LaterUseKind::TraitCapture
                 } else if location.statement_index == block.statements.len() {
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index dbd4cac7b14..579ce90a760 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -200,7 +200,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
     /// increment the counter.
     ///
     /// This is _not_ idempotent. Call `give_region_a_name` when possible.
-    fn synthesize_region_name(&self) -> Symbol {
+    pub(crate) fn synthesize_region_name(&self) -> Symbol {
         let c = self.next_region_name.replace_with(|counter| *counter + 1);
         Symbol::intern(&format!("'{:?}", c))
     }