Improve error message and add tests for borrowck match handling
This commit is contained in:
parent
f66e4697ae
commit
c15437c0c6
@ -1330,22 +1330,30 @@ pub(super) fn report_illegal_mutation_of_borrowed(
|
||||
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,
|
||||
|
58
src/test/ui/nll/match-cfg-fake-edges.rs
Normal file
58
src/test/ui/nll/match-cfg-fake-edges.rs
Normal file
@ -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() {}
|
34
src/test/ui/nll/match-cfg-fake-edges.stderr
Normal file
34
src/test/ui/nll/match-cfg-fake-edges.stderr
Normal file
@ -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`.
|
@ -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 => (),
|
||||
|
@ -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`.
|
||||
|
Loading…
Reference in New Issue
Block a user