about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-08-16 11:00:25 +0000
committerbors <bors@rust-lang.org>2022-08-16 11:00:25 +0000
commita39bdb1d6b9eaf23f2636baee0949d67890abcd8 (patch)
tree134af937e12c013ef621e3972a60934f652d99ea /compiler
parent14a459bf37bc19476d43e0045d078121c12d3fef (diff)
parent15713e1717219be78c46234d2255fb105f87c02c (diff)
downloadrust-a39bdb1d6b9eaf23f2636baee0949d67890abcd8.tar.gz
rust-a39bdb1d6b9eaf23f2636baee0949d67890abcd8.zip
Auto merge of #99612 - yanchen4791:issue-95079-fix, r=compiler-errors
Fix #95079 unhelpful error when missing move in nested closure

Fix #95079 by adding help for missing move in nested closure
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs37
1 files changed, 37 insertions, 0 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index bd3a2a3d694..0dce5be953e 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -546,6 +546,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
              executing...",
         );
         diag.note("...therefore, they cannot allow references to captured variables to escape");
+        self.suggest_move_on_borrowing_closure(&mut diag);
 
         diag
     }
@@ -716,6 +717,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
 
         self.add_static_impl_trait_suggestion(&mut diag, *fr, fr_name, *outlived_fr);
         self.suggest_adding_lifetime_params(&mut diag, *fr, *outlived_fr);
+        self.suggest_move_on_borrowing_closure(&mut diag);
 
         diag
     }
@@ -901,4 +903,39 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
 
         suggest_adding_lifetime_params(self.infcx.tcx, sub, ty_sup, ty_sub, diag);
     }
+
+    fn suggest_move_on_borrowing_closure(&self, diag: &mut Diagnostic) {
+        let map = self.infcx.tcx.hir();
+        let body_id = map.body_owned_by(self.mir_def_id());
+        let expr = &map.body(body_id).value;
+        let mut closure_span = None::<rustc_span::Span>;
+        match expr.kind {
+            hir::ExprKind::MethodCall(.., args, _) => {
+                // only the first closre parameter of the method. args[0] is MethodCall PathSegment
+                for i in 1..args.len() {
+                    if let hir::ExprKind::Closure(..) = args[i].kind {
+                        closure_span = Some(args[i].span.shrink_to_lo());
+                        break;
+                    }
+                }
+            }
+            hir::ExprKind::Block(blk, _) => {
+                if let Some(ref expr) = blk.expr {
+                    // only when the block is a closure
+                    if let hir::ExprKind::Closure(..) = expr.kind {
+                        closure_span = Some(expr.span.shrink_to_lo());
+                    }
+                }
+            }
+            _ => {}
+        }
+        if let Some(closure_span) = closure_span {
+            diag.span_suggestion_verbose(
+                closure_span,
+                format!("consider adding 'move' keyword before the nested closure"),
+                "move ",
+                Applicability::MaybeIncorrect,
+            );
+        }
+    }
 }