diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 4d65862375a9..744dd61f4f59 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 000000000000..a3add8856dfa --- /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 000000000000..a855b28a978d --- /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 f359800812c8..cb8ea2c3d26b 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 2cbfeb886b57..b6302b3a65d3 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`.