]> git.lizzy.rs Git - rust.git/commitdiff
When moving out of a for loop head, suggest borrowing it in nll mode
authorEsteban Küber <esteban@kuber.com.ar>
Tue, 26 Mar 2019 02:11:41 +0000 (19:11 -0700)
committerEsteban Küber <esteban@kuber.com.ar>
Tue, 26 Mar 2019 02:29:02 +0000 (19:29 -0700)
src/librustc_mir/borrow_check/error_reporting.rs
src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
src/test/ui/augmented-assignments.nll.stderr
src/test/ui/regions/region-bound-on-closure-outlives-call.nll.stderr
src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr
src/test/ui/suggestions/borrow-for-loop-head.nll.stderr

index 14289381aef456c4ff62d2625bbce3bdf0c64e0b..88ff231202085421ecc8e5b8d7be1e3635eda02b 100644 (file)
@@ -19,6 +19,7 @@
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use syntax_pos::Span;
+use syntax::source_map::CompilerDesugaringKind;
 
 use super::borrow_set::BorrowData;
 use super::{Context, MirBorrowckCtxt};
@@ -154,6 +155,18 @@ pub(super) fn report_use_of_moved_or_uninitialized(
                         span,
                         format!("value moved{} here, in previous iteration of loop", move_msg),
                     );
+                    if Some(CompilerDesugaringKind::ForLoop) == span.compiler_desugaring_kind() {
+                        if let Ok(snippet) = self.infcx.tcx.sess.source_map()
+                            .span_to_snippet(span)
+                        {
+                            err.span_suggestion(
+                                move_span,
+                                "consider borrowing this to avoid moving it into the for loop",
+                                format!("&{}", snippet),
+                                Applicability::MaybeIncorrect,
+                            );
+                        }
+                    }
                     is_loop_move = true;
                 } else if move_site.traversed_back_edge {
                     err.span_label(
@@ -291,8 +304,11 @@ pub(super) fn report_move_out_while_borrowed(
             format!("move occurs due to use{}", move_spans.describe())
         );
 
-        self.explain_why_borrow_contains_point(context, borrow, None)
-            .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");
+        self.explain_why_borrow_contains_point(
+            context,
+            borrow,
+            None,
+        ).add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", Some(borrow_span));
         err.buffer(&mut self.errors_buffer);
     }
 
@@ -329,7 +345,7 @@ pub(super) fn report_use_while_mutably_borrowed(
         });
 
         self.explain_why_borrow_contains_point(context, borrow, None)
-            .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");
+            .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None);
         err.buffer(&mut self.errors_buffer);
     }
 
@@ -542,8 +558,13 @@ pub(super) fn report_conflicting_borrow(
             ));
         }
 
-        explanation
-            .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, first_borrow_desc);
+        explanation.add_explanation_to_diagnostic(
+            self.infcx.tcx,
+            self.mir,
+            &mut err,
+            first_borrow_desc,
+            None,
+        );
 
         err.buffer(&mut self.errors_buffer);
     }
@@ -866,7 +887,13 @@ fn report_local_value_does_not_live_long_enough(
 
             if let BorrowExplanation::MustBeValidFor { .. } = explanation {
             } else {
-                explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");
+                explanation.add_explanation_to_diagnostic(
+                    self.infcx.tcx,
+                    self.mir,
+                    &mut err,
+                    "",
+                    None,
+                );
             }
         } else {
             err.span_label(borrow_span, "borrowed value does not live long enough");
@@ -886,7 +913,7 @@ fn report_local_value_does_not_live_long_enough(
                 format!("value captured here{}", within),
             );
 
-            explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");
+            explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None);
         }
 
         err
@@ -946,7 +973,7 @@ fn report_borrow_conflicts_with_destructor(
             _ => {}
         }
 
-        explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");
+        explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None);
 
         err.buffer(&mut self.errors_buffer);
     }
@@ -1027,7 +1054,7 @@ fn report_temporary_value_does_not_live_long_enough(
             }
             _ => {}
         }
-        explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");
+        explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None);
 
         let within = if borrow_spans.for_generator() {
             " by generator"
@@ -1367,7 +1394,7 @@ pub(super) fn report_illegal_mutation_of_borrowed(
         );
 
         self.explain_why_borrow_contains_point(context, loan, None)
-            .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");
+            .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None);
 
         err.buffer(&mut self.errors_buffer);
     }
index dfa5af444d37ec76be09ddd0b2dd3ea3f5f42b65..67b77605f3c92f4a8b3ea45247a13b8cd8686722 100644 (file)
@@ -56,17 +56,23 @@ pub(in crate::borrow_check) fn add_explanation_to_diagnostic<'cx, 'gcx, 'tcx>(
         mir: &Mir<'tcx>,
         err: &mut DiagnosticBuilder<'_>,
         borrow_desc: &str,
+        borrow_span: Option<Span>,
     ) {
         match *self {
             BorrowExplanation::UsedLater(later_use_kind, var_or_use_span) => {
                 let message = match later_use_kind {
-                    LaterUseKind::TraitCapture => "borrow later captured here by trait object",
-                    LaterUseKind::ClosureCapture => "borrow later captured here by closure",
-                    LaterUseKind::Call => "borrow later used by call",
-                    LaterUseKind::FakeLetRead => "borrow later stored here",
-                    LaterUseKind::Other => "borrow later used here",
+                    LaterUseKind::TraitCapture => "captured here by trait object",
+                    LaterUseKind::ClosureCapture => "captured here by closure",
+                    LaterUseKind::Call => "used by call",
+                    LaterUseKind::FakeLetRead => "stored here",
+                    LaterUseKind::Other => "used here",
                 };
-                err.span_label(var_or_use_span, format!("{}{}", borrow_desc, message));
+                if !borrow_span.map(|sp| sp.overlaps(var_or_use_span)).unwrap_or(false) {
+                    err.span_label(
+                        var_or_use_span,
+                        format!("{}borrow later {}", borrow_desc, message),
+                    );
+                }
             }
             BorrowExplanation::UsedLaterInLoop(later_use_kind, var_or_use_span) => {
                 let message = match later_use_kind {
index 08f06e90162b4935c2d774059784b08e17cec68b..e205e2a87810f7da0a39b88c1bb8d75021a2368b 100644 (file)
@@ -1,18 +1,11 @@
 error[E0505]: cannot move out of `x` because it is borrowed
   --> $DIR/augmented-assignments.rs:16:5
    |
-LL |       x
-   |       -
-   |       |
-   |  _____borrow of `x` occurs here
-   | |
-LL | |
-LL | |     +=
-LL | |     x;
-   | |     ^
-   | |     |
-   | |_____move out of `x` occurs here
-   |       borrow later used here
+LL |     x
+   |     - borrow of `x` occurs here
+...
+LL |     x;
+   |     ^ move out of `x` occurs here
 
 error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable
   --> $DIR/augmented-assignments.rs:21:5
index bce310bafaa92b2fc8d159138351759d6b308a70..d455902ee8c07ca294bf368ead705cbb6a006747 100644 (file)
@@ -14,11 +14,10 @@ error[E0505]: cannot move out of `f` because it is borrowed
   --> $DIR/region-bound-on-closure-outlives-call.rs:3:25
    |
 LL |     (|x| f(x))(call_rec(f))
-   |     ----------          ^ move out of `f` occurs here
-   |     ||   |
-   |     ||   borrow occurs due to use in closure
-   |     |borrow of `f` occurs here
-   |     borrow later used by call
+   |      --- -              ^ move out of `f` occurs here
+   |      |   |
+   |      |   borrow occurs due to use in closure
+   |      borrow of `f` occurs here
 
 error: aborting due to previous error
 
index 80dc3ef2f80f2a54a9af106ec272695aedaaf844..1a5ab7a7d56a032e65bb23e38f49ad20131df1fa 100644 (file)
@@ -42,7 +42,6 @@ LL |     f(Box::new(|a| {
    |     -          ^^^ move out of `f` occurs here
    |     |
    |     borrow of `f` occurs here
-   |     borrow later used by call
 LL |         foo(f);
    |             - move occurs due to use in closure
 
index 6450f7f52a47becfdbd94468d6c60d7c446cdefc..96dbdec7074a9977a52e25b36b1425b8e467898f 100644 (file)
@@ -2,10 +2,7 @@ error[E0505]: cannot move out of `a` because it is borrowed
   --> $DIR/borrow-for-loop-head.rs:4:18
    |
 LL |     for i in &a {
-   |              --
-   |              |
-   |              borrow of `a` occurs here
-   |              borrow later used here
+   |              -- borrow of `a` occurs here
 LL |         for j in a {
    |                  ^ move out of `a` occurs here
 
@@ -17,6 +14,10 @@ LL |     let a = vec![1, 2, 3];
 LL |     for i in &a {
 LL |         for j in a {
    |                  ^ value moved here, in previous iteration of loop
+help: consider borrowing this to avoid moving it into the for loop
+   |
+LL |         for j in &a {
+   |                  ^^
 
 error: aborting due to 2 previous errors