about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYuki Okushi <yuki.okushi@huawei.com>2021-06-16 09:44:47 +0900
committerYuki Okushi <yuki.okushi@huawei.com>2021-06-16 09:47:37 +0900
commitc8a8a23a31e9e4831ccab4efbc085852b7a86fa5 (patch)
tree074d75d29709da564dcde36f8981b9505897a9a7
parent607d6b00d4e0e0475b8de9d0c870b7126fdcdf6b (diff)
downloadrust-c8a8a23a31e9e4831ccab4efbc085852b7a86fa5.tar.gz
rust-c8a8a23a31e9e4831ccab4efbc085852b7a86fa5.zip
Do not emit invalid suggestions on multiple mutable borrow errors
-rw-r--r--compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs8
-rw-r--r--compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs26
-rw-r--r--src/test/ui/borrowck/issue-85581.rs15
-rw-r--r--src/test/ui/borrowck/issue-85581.stderr17
4 files changed, 58 insertions, 8 deletions
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
index 8b0761889b8..a0c9b43d5af 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
@@ -453,6 +453,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 &mut err,
                 "",
                 Some(borrow_span),
+                None,
             );
         err.buffer(&mut self.errors_buffer);
     }
@@ -498,6 +499,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 &mut err,
                 "",
                 None,
+                None,
             );
         err
     }
@@ -718,6 +720,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             &mut err,
             first_borrow_desc,
             None,
+            Some((issued_span, span)),
         );
 
         err
@@ -1076,6 +1079,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     &mut err,
                     "",
                     None,
+                    None,
                 );
             }
         } else {
@@ -1093,6 +1097,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 &mut err,
                 "",
                 None,
+                None,
             );
         }
 
@@ -1158,6 +1163,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             &mut err,
             "",
             None,
+            None,
         );
 
         err.buffer(&mut self.errors_buffer);
@@ -1236,6 +1242,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             &mut err,
             "",
             None,
+            None,
         );
 
         let within = if borrow_spans.for_generator() { " by generator" } else { "" };
@@ -1614,6 +1621,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             &mut err,
             "",
             None,
+            None,
         );
 
         self.explain_deref_coercion(loan, &mut err);
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
index e9f1ecb9bbc..76de010d139 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
@@ -66,6 +66,7 @@ impl BorrowExplanation {
         err: &mut DiagnosticBuilder<'_>,
         borrow_desc: &str,
         borrow_span: Option<Span>,
+        multiple_borrow_span: Option<(Span, Span)>,
     ) {
         match *self {
             BorrowExplanation::UsedLater(later_use_kind, var_or_use_span, path_span) => {
@@ -192,14 +193,23 @@ impl BorrowExplanation {
 
                         if let Some(info) = &local_decl.is_block_tail {
                             if info.tail_result_is_ignored {
-                                err.span_suggestion_verbose(
-                                    info.span.shrink_to_hi(),
-                                    "consider adding semicolon after the expression so its \
-                                     temporaries are dropped sooner, before the local variables \
-                                     declared by the block are dropped",
-                                    ";".to_string(),
-                                    Applicability::MaybeIncorrect,
-                                );
+                                // #85581: If the first mutable borrow's scope contains
+                                // the second borrow, this suggestion isn't helpful.
+                                if !multiple_borrow_span
+                                    .map(|(old, new)| {
+                                        old.to(info.span.shrink_to_hi()).contains(new)
+                                    })
+                                    .unwrap_or(false)
+                                {
+                                    err.span_suggestion_verbose(
+                                        info.span.shrink_to_hi(),
+                                        "consider adding semicolon after the expression so its \
+                                        temporaries are dropped sooner, before the local variables \
+                                        declared by the block are dropped",
+                                        ";".to_string(),
+                                        Applicability::MaybeIncorrect,
+                                    );
+                                }
                             } else {
                                 err.note(
                                     "the temporary is part of an expression at the end of a \
diff --git a/src/test/ui/borrowck/issue-85581.rs b/src/test/ui/borrowck/issue-85581.rs
new file mode 100644
index 00000000000..ccc120c5421
--- /dev/null
+++ b/src/test/ui/borrowck/issue-85581.rs
@@ -0,0 +1,15 @@
+// Regression test of #85581.
+// Checks not to suggest to add `;` when the second mutable borrow
+// is in the first's scope.
+
+use std::collections::BinaryHeap;
+
+fn foo(heap: &mut BinaryHeap<i32>) {
+    match heap.peek_mut() {
+        Some(_) => { heap.pop(); },
+        //~^ ERROR: cannot borrow `*heap` as mutable more than once at a time
+        None => (),
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/issue-85581.stderr b/src/test/ui/borrowck/issue-85581.stderr
new file mode 100644
index 00000000000..29c0429f2a0
--- /dev/null
+++ b/src/test/ui/borrowck/issue-85581.stderr
@@ -0,0 +1,17 @@
+error[E0499]: cannot borrow `*heap` as mutable more than once at a time
+  --> $DIR/issue-85581.rs:9:22
+   |
+LL |     match heap.peek_mut() {
+   |           ---------------
+   |           |
+   |           first mutable borrow occurs here
+   |           a temporary with access to the first borrow is created here ...
+LL |         Some(_) => { heap.pop(); },
+   |                      ^^^^ second mutable borrow occurs here
+...
+LL | }
+   | - ... and the first borrow might be used here, when that temporary is dropped and runs the destructor for type `Option<PeekMut<'_, i32>>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.