about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorSantiago Pastorino <spastorino@gmail.com>2018-04-09 12:42:17 -0300
committerSantiago Pastorino <spastorino@gmail.com>2018-04-09 17:35:28 -0300
commit2e87dbbde14b5939a47b3507660a2bab25ef93a9 (patch)
treebaf3e26ed3cc9bbd3d0d66ed3dc35ae2784779c7 /src
parent4b9b70c394e7f341b4016fce4cbf763d404b26f9 (diff)
downloadrust-2e87dbbde14b5939a47b3507660a2bab25ef93a9.tar.gz
rust-2e87dbbde14b5939a47b3507660a2bab25ef93a9.zip
Fix ICE when a borrow is used after drop
ht @nickfrostatx for the first initial patch
Diffstat (limited to 'src')
-rw-r--r--src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs34
-rw-r--r--src/test/ui/issue-47646.rs26
-rw-r--r--src/test/ui/issue-47646.stderr18
3 files changed, 67 insertions, 11 deletions
diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
index 4031bd5369d..b6efe884fc3 100644
--- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
@@ -59,17 +59,29 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 
                     Cause::DropVar(local, location) => {
                         match find_drop_use(mir, regioncx, borrow, location, local) {
-                            Some(p) => {
-                                let local_name = mir.local_decls[local].name.unwrap();
-
-                                err.span_label(
-                                    mir.source_info(p).span,
-                                    format!(
-                                        "borrow later used here, when `{}` is dropped",
-                                        local_name
-                                    ),
-                                );
-                            }
+                            Some(p) => match &mir.local_decls[local].name {
+                                Some(local_name) => {
+                                    err.span_label(
+                                        mir.source_info(p).span,
+                                        format!(
+                                            "borrow later used here, when `{}` is dropped",
+                                            local_name
+                                        ),
+                                    );
+                                }
+                                None => {
+                                    err.span_label(
+                                        mir.local_decls[local].source_info.span,
+                                        "borrow may end up in a temporary, created here",
+                                    );
+
+                                    err.span_label(
+                                        mir.source_info(p).span,
+                                        "temporary later dropped here, \
+                                         potentially using the reference",
+                                    );
+                                }
+                            },
 
                             None => {
                                 span_bug!(
diff --git a/src/test/ui/issue-47646.rs b/src/test/ui/issue-47646.rs
new file mode 100644
index 00000000000..7a6d6dd3fe1
--- /dev/null
+++ b/src/test/ui/issue-47646.rs
@@ -0,0 +1,26 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(warnings)]
+#![feature(nll)]
+
+use std::collections::BinaryHeap;
+
+fn main() {
+    let mut heap: BinaryHeap<i32> = BinaryHeap::new();
+    let borrow = heap.peek_mut();
+
+    match (borrow, ()) {
+        (Some(_), ()) => {
+            println!("{:?}", heap); //~ ERROR cannot borrow `heap` as immutable
+        }
+        _ => {}
+    };
+}
diff --git a/src/test/ui/issue-47646.stderr b/src/test/ui/issue-47646.stderr
new file mode 100644
index 00000000000..b1289146e0e
--- /dev/null
+++ b/src/test/ui/issue-47646.stderr
@@ -0,0 +1,18 @@
+error[E0502]: cannot borrow `heap` as immutable because it is also borrowed as mutable
+  --> $DIR/issue-47646.rs:22:30
+   |
+LL |     let borrow = heap.peek_mut();
+   |                  ---- mutable borrow occurs here
+LL | 
+LL |     match (borrow, ()) {
+   |           ------------ borrow may end up in a temporary, created here
+LL |         (Some(_), ()) => {
+LL |             println!("{:?}", heap); //~ ERROR cannot borrow `heap` as immutable
+   |                              ^^^^ immutable borrow occurs here
+...
+LL |     };
+   |      - temporary later dropped here, potentially using the reference
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.