about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_mir/borrow_check/error_reporting.rs30
-rw-r--r--src/test/ui/nll/match-cfg-fake-edges.rs58
-rw-r--r--src/test/ui/nll/match-cfg-fake-edges.stderr34
-rw-r--r--src/test/ui/nll/match-guards-partially-borrow.rs14
-rw-r--r--src/test/ui/nll/match-guards-partially-borrow.stderr51
5 files changed, 144 insertions, 43 deletions
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index 4d65862375a..744dd61f4f5 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -1330,22 +1330,30 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         let loan_span = loan_spans.args_or_use();
 
         let tcx = self.infcx.tcx;
-        let mut err = if loan.kind == BorrowKind::Shallow {
-            tcx.cannot_mutate_in_match_guard(
+        if loan.kind == BorrowKind::Shallow {
+            let mut err = tcx.cannot_mutate_in_match_guard(
                 span,
                 loan_span,
                 &self.describe_place(place).unwrap_or_else(|| "_".to_owned()),
                 "assign",
                 Origin::Mir,
-            )
-        } else {
-            tcx.cannot_assign_to_borrowed(
-                span,
-                loan_span,
-                &self.describe_place(place).unwrap_or_else(|| "_".to_owned()),
-                Origin::Mir,
-            )
-        };
+            );
+            loan_spans.var_span_label(
+                &mut err,
+                format!("borrow occurs due to use{}", loan_spans.describe()),
+            );
+
+            err.buffer(&mut self.errors_buffer);
+
+            return;
+        }
+
+        let mut err = tcx.cannot_assign_to_borrowed(
+            span,
+            loan_span,
+            &self.describe_place(place).unwrap_or_else(|| "_".to_owned()),
+            Origin::Mir,
+        );
 
         loan_spans.var_span_label(
             &mut err,
diff --git a/src/test/ui/nll/match-cfg-fake-edges.rs b/src/test/ui/nll/match-cfg-fake-edges.rs
new file mode 100644
index 00000000000..a3add8856df
--- /dev/null
+++ b/src/test/ui/nll/match-cfg-fake-edges.rs
@@ -0,0 +1,58 @@
+// Test that we have enough false edges to avoid exposing the exact matching
+// algorithm in borrow checking.
+
+#![feature(nll, bind_by_move_pattern_guards)]
+
+fn guard_always_precedes_arm(y: i32) {
+    let mut x;
+    // x should always be initialized, as the only way to reach the arm is
+    // through the guard.
+    match y {
+        0 | 2 if { x = 2; true } => x,
+        _ => 2,
+    };
+}
+
+fn guard_may_be_skipped(y: i32) {
+    let x;
+    // Even though x *is* always initialized, we don't want to have borrowck
+    // results be based on whether patterns are exhaustive.
+    match y {
+        _ if { x = 2; true } => 1,
+        _ if {
+            x; //~ ERROR use of possibly uninitialized variable: `x`
+            false
+        } => 2,
+        _ => 3,
+    };
+}
+
+fn guard_may_be_taken(y: bool) {
+    let x = String::new();
+    // Even though x *is* never moved before the use, we don't want to have
+    // borrowck results be based on whether patterns are disjoint.
+    match y {
+        false if { drop(x); true } => 1,
+        true => {
+            x; //~ ERROR use of moved value: `x`
+            2
+        }
+        false => 3,
+    };
+}
+
+fn all_previous_tests_may_be_done(y: &mut (bool, bool)) {
+    let r = &mut y.1;
+    // We don't actually test y.1 to select the second arm, but we don't want
+    // borrowck results to be based on the order we match patterns.
+    match y {
+        (false, true) => 1, //~ ERROR cannot use `y.1` because it was mutably borrowed
+        (true, _) => {
+            r;
+            2
+        }
+        (false, _) => 3,
+    };
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/match-cfg-fake-edges.stderr b/src/test/ui/nll/match-cfg-fake-edges.stderr
new file mode 100644
index 00000000000..a855b28a978
--- /dev/null
+++ b/src/test/ui/nll/match-cfg-fake-edges.stderr
@@ -0,0 +1,34 @@
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/match-cfg-fake-edges.rs:23:13
+   |
+LL |             x; //~ ERROR use of possibly uninitialized variable: `x`
+   |             ^ use of possibly uninitialized `x`
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/match-cfg-fake-edges.rs:37:13
+   |
+LL |     let x = String::new();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+...
+LL |         false if { drop(x); true } => 1,
+   |                         - value moved here
+LL |         true => {
+LL |             x; //~ ERROR use of moved value: `x`
+   |             ^ value used here after move
+
+error[E0503]: cannot use `y.1` because it was mutably borrowed
+  --> $DIR/match-cfg-fake-edges.rs:49:17
+   |
+LL |     let r = &mut y.1;
+   |             -------- borrow of `y.1` occurs here
+...
+LL |         (false, true) => 1, //~ ERROR cannot use `y.1` because it was mutably borrowed
+   |                 ^^^^ use of borrowed `y.1`
+LL |         (true, _) => {
+LL |             r;
+   |             - borrow later used here
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0381, E0382, E0503.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/nll/match-guards-partially-borrow.rs b/src/test/ui/nll/match-guards-partially-borrow.rs
index f359800812c..cb8ea2c3d26 100644
--- a/src/test/ui/nll/match-guards-partially-borrow.rs
+++ b/src/test/ui/nll/match-guards-partially-borrow.rs
@@ -30,7 +30,7 @@ fn ok_indirect_mutation_in_guard(mut p: &bool) {
 
 fn mutation_invalidates_pattern_in_guard(mut q: bool) {
     match q {
-        // s doesn't match the pattern with the guard by the end of the guard.
+        // q doesn't match the pattern with the guard by the end of the guard.
         false if {
             q = true; //~ ERROR
             true
@@ -41,7 +41,7 @@ fn mutation_invalidates_pattern_in_guard(mut q: bool) {
 
 fn mutation_invalidates_previous_pattern_in_guard(mut r: bool) {
     match r {
-        // s matches a previous pattern by the end of the guard.
+        // r matches a previous pattern by the end of the guard.
         true => (),
         _ if {
             r = true; //~ ERROR
@@ -116,6 +116,16 @@ fn bad_mutation_in_guard4(mut w: (&mut bool,)) {
     }
 }
 
+fn bad_mutation_in_guard5(mut t: bool) {
+    match t {
+        s if {
+            t = !t; //~ ERROR
+            false
+        } => (), // What value should `s` have in the arm?
+        _ => (),
+    }
+}
+
 fn bad_indirect_mutation_in_guard(mut y: &bool) {
     match *y {
         true => (),
diff --git a/src/test/ui/nll/match-guards-partially-borrow.stderr b/src/test/ui/nll/match-guards-partially-borrow.stderr
index 2cbfeb886b5..b6302b3a65d 100644
--- a/src/test/ui/nll/match-guards-partially-borrow.stderr
+++ b/src/test/ui/nll/match-guards-partially-borrow.stderr
@@ -6,9 +6,6 @@ LL |     match q {
 ...
 LL |             q = true; //~ ERROR
    |             ^^^^^^^^ cannot assign
-...
-LL |         _ => (),
-   |         - borrow later used here
 
 error[E0510]: cannot assign `r` in match guard
   --> $DIR/match-guards-partially-borrow.rs:47:13
@@ -18,9 +15,6 @@ LL |     match r {
 ...
 LL |             r = true; //~ ERROR
    |             ^^^^^^^^ cannot assign
-...
-LL |         _ => (),
-   |         - borrow later used here
 
 error[E0503]: cannot use `s` because it was mutably borrowed
   --> $DIR/match-guards-partially-borrow.rs:56:11
@@ -41,9 +35,6 @@ LL |     match t {
 ...
 LL |             t = true; //~ ERROR
    |             ^^^^^^^^ cannot assign
-...
-LL |         false => (),
-   |         ----- borrow later used here
 
 error[E0506]: cannot assign to `u` because it is borrowed
   --> $DIR/match-guards-partially-borrow.rs:83:13
@@ -53,8 +44,8 @@ LL |     match u {
 ...
 LL |             u = true; //~ ERROR
    |             ^^^^^^^^ assignment to borrowed `u` occurs here
-...
-LL |         x => (),
+LL |             false
+LL |         } => (),
    |         - borrow later used here
 
 error[E0510]: cannot mutably borrow `x.0` in match guard
@@ -74,59 +65,59 @@ LL |     match w {
 ...
 LL |             *w.0 = true; //~ ERROR
    |             ^^^^^^^^^^^ assignment to borrowed `*w.0` occurs here
-...
-LL |         x => (),
+LL |             false
+LL |         } => (),
+   |         - borrow later used here
+
+error[E0506]: cannot assign to `t` because it is borrowed
+  --> $DIR/match-guards-partially-borrow.rs:122:13
+   |
+LL |     match t {
+   |           - borrow of `t` occurs here
+LL |         s if {
+LL |             t = !t; //~ ERROR
+   |             ^^^^^^ assignment to borrowed `t` occurs here
+LL |             false
+LL |         } => (), // What value should `s` have in the arm?
    |         - borrow later used here
 
 error[E0510]: cannot assign `y` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:123:13
+  --> $DIR/match-guards-partially-borrow.rs:133:13
    |
 LL |     match *y {
    |           -- value is immutable in match guard
 ...
 LL |             y = &true; //~ ERROR
    |             ^^^^^^^^^ cannot assign
-...
-LL |         false => (),
-   |         ----- borrow later used here
 
 error[E0510]: cannot assign `z` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:134:13
+  --> $DIR/match-guards-partially-borrow.rs:144:13
    |
 LL |     match z {
    |           - value is immutable in match guard
 ...
 LL |             z = &true; //~ ERROR
    |             ^^^^^^^^^ cannot assign
-...
-LL |         &false => (),
-   |         ------ borrow later used here
 
 error[E0510]: cannot assign `a` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:146:13
+  --> $DIR/match-guards-partially-borrow.rs:156:13
    |
 LL |     match a {
    |           - value is immutable in match guard
 ...
 LL |             a = &true; //~ ERROR
    |             ^^^^^^^^^ cannot assign
-...
-LL |         false => (),
-   |         ----- borrow later used here
 
 error[E0510]: cannot assign `b` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:157:13
+  --> $DIR/match-guards-partially-borrow.rs:167:13
    |
 LL |     match b {
    |           - value is immutable in match guard
 ...
 LL |             b = &true; //~ ERROR
    |             ^^^^^^^^^ cannot assign
-...
-LL |         &b => (),
-   |         -- borrow later used here
 
-error: aborting due to 11 previous errors
+error: aborting due to 12 previous errors
 
 Some errors occurred: E0503, E0506, E0510.
 For more information about an error, try `rustc --explain E0503`.