about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2024-04-19 04:26:42 +0000
committerEsteban Küber <esteban@kuber.com.ar>2024-04-24 22:21:16 +0000
commitad9a5a5f9f5dcd440eff22f29c11b4129d2ee338 (patch)
tree63ac80a97e74beae56759d716e654e339f70b1c1 /compiler/rustc_trait_selection/src
parentd68f2a6b71df3a4524c390f683dbd7a925ed207f (diff)
downloadrust-ad9a5a5f9f5dcd440eff22f29c11b4129d2ee338.tar.gz
rust-ad9a5a5f9f5dcd440eff22f29c11b4129d2ee338.zip
Suggest cloning captured binding in `move` closure
```
error[E0507]: cannot move out of `bar`, a captured variable in an `FnMut` closure
  --> $DIR/borrowck-move-by-capture.rs:9:29
   |
LL |     let bar: Box<_> = Box::new(3);
   |         --- captured outer variable
LL |     let _g = to_fn_mut(|| {
   |                        -- captured by this `FnMut` closure
LL |         let _h = to_fn_once(move || -> isize { *bar });
   |                             ^^^^^^^^^^^^^^^^   ----
   |                             |                  |
   |                             |                  variable moved due to use in closure
   |                             |                  move occurs because `bar` has type `Box<isize>`, which does not implement the `Copy` trait
   |                             `bar` is moved here
   |
help: clone the value before moving it into the closure
   |
LL ~         let value = bar.clone();
LL ~         let _h = to_fn_once(move || -> isize { value });
   |
```
Diffstat (limited to 'compiler/rustc_trait_selection/src')
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs11
1 files changed, 10 insertions, 1 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 4731f11ad32..e50edfdc656 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -50,12 +50,13 @@ pub struct FindExprBySpan<'hir> {
     pub span: Span,
     pub result: Option<&'hir hir::Expr<'hir>>,
     pub ty_result: Option<&'hir hir::Ty<'hir>>,
+    pub include_closures: bool,
     pub tcx: TyCtxt<'hir>,
 }
 
 impl<'hir> FindExprBySpan<'hir> {
     pub fn new(span: Span, tcx: TyCtxt<'hir>) -> Self {
-        Self { span, result: None, ty_result: None, tcx }
+        Self { span, result: None, ty_result: None, tcx, include_closures: false }
     }
 }
 
@@ -70,9 +71,17 @@ impl<'v> Visitor<'v> for FindExprBySpan<'v> {
         if self.span == ex.span {
             self.result = Some(ex);
         } else {
+            if let hir::ExprKind::Closure(..) = ex.kind
+                && self.include_closures
+                && let closure_header_sp = self.span.with_hi(ex.span.hi())
+                && closure_header_sp == ex.span
+            {
+                self.result = Some(ex);
+            }
             hir::intravisit::walk_expr(self, ex);
         }
     }
+
     fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
         if self.span == ty.span {
             self.ty_result = Some(ty);