Add tests
This commit is contained in:
parent
ceab6128fa
commit
50103ab14d
4 changed files with 165 additions and 67 deletions
|
@ -3,15 +3,43 @@
|
||||||
|
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
fn all_patterns_are_tested() {
|
||||||
|
// Even though `x` is never actually moved out of, we don't want borrowck results to be based on
|
||||||
|
// whether MIR lowering reveals which patterns are unreachable.
|
||||||
|
let x = String::new();
|
||||||
|
let _ = match true {
|
||||||
|
_ => {},
|
||||||
|
_ => drop(x),
|
||||||
|
};
|
||||||
|
// Borrowck must not know the second arm is never run.
|
||||||
|
drop(x); //~ ERROR use of moved value
|
||||||
|
|
||||||
|
let x = (String::new(), String::new());
|
||||||
|
match x {
|
||||||
|
(y, _) | (_, y) => (),
|
||||||
|
}
|
||||||
|
&x.0; //~ ERROR borrow of moved value
|
||||||
|
// Borrowck must not know the second pattern never matches.
|
||||||
|
&x.1; //~ ERROR borrow of moved value
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
fn guard_always_precedes_arm(y: i32) {
|
fn guard_always_precedes_arm(y: i32) {
|
||||||
let mut x;
|
|
||||||
// x should always be initialized, as the only way to reach the arm is
|
// x should always be initialized, as the only way to reach the arm is
|
||||||
// through the guard.
|
// through the guard.
|
||||||
|
let mut x;
|
||||||
match y {
|
match y {
|
||||||
0 | 2 if { x = 2; true } => x,
|
0 | 2 if { x = 2; true } => x,
|
||||||
_ => 2,
|
_ => 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut x;
|
||||||
|
match y {
|
||||||
|
_ => 2,
|
||||||
|
0 | 2 if { x = 2; true } => x,
|
||||||
|
};
|
||||||
|
|
||||||
let mut x;
|
let mut x;
|
||||||
match y {
|
match y {
|
||||||
0 | 2 if let Some(()) = { x = 2; Some(()) } => x,
|
0 | 2 if let Some(()) = { x = 2; Some(()) } => x,
|
||||||
|
@ -19,51 +47,58 @@ fn guard_always_precedes_arm(y: i32) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
fn guard_may_be_skipped(y: i32) {
|
fn guard_may_be_skipped(y: i32) {
|
||||||
|
// Even though x *is* always initialized, we don't want to have borrowck results be based on
|
||||||
|
// whether MIR lowering reveals which patterns are exhaustive.
|
||||||
|
let x;
|
||||||
|
match y {
|
||||||
|
_ if { x = 2; true } => {},
|
||||||
|
// Borrowck must not know the guard is always run.
|
||||||
|
_ => drop(x), //~ ERROR used binding `x` is possibly-uninitialized
|
||||||
|
};
|
||||||
|
|
||||||
let x;
|
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 {
|
match y {
|
||||||
_ if { x = 2; true } => 1,
|
_ if { x = 2; true } => 1,
|
||||||
_ if {
|
// Borrowck must not know the guard is always run.
|
||||||
x; //~ ERROR E0381
|
_ if { x; false } => 2, //~ ERROR used binding `x` isn't initialized
|
||||||
false
|
|
||||||
} => 2,
|
|
||||||
_ => 3,
|
_ => 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
let x;
|
let x;
|
||||||
match y {
|
match y {
|
||||||
_ if let Some(()) = { x = 2; Some(()) } => 1,
|
_ if let Some(()) = { x = 2; Some(()) } => 1,
|
||||||
_ if let Some(()) = {
|
_ if let Some(()) = { x; None } => 2, //~ ERROR used binding `x` isn't initialized
|
||||||
x; //~ ERROR E0381
|
|
||||||
None
|
|
||||||
} => 2,
|
|
||||||
_ => 3,
|
_ => 3,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
fn guard_may_be_taken(y: bool) {
|
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
|
// Even though x *is* never moved before the use, we don't want to have
|
||||||
// borrowck results be based on whether patterns are disjoint.
|
// borrowck results be based on whether patterns are disjoint.
|
||||||
|
let x = String::new();
|
||||||
match y {
|
match y {
|
||||||
false if { drop(x); true } => 1,
|
false if { drop(x); true } => {},
|
||||||
true => {
|
// Borrowck must not know the guard is not run in the `true` case.
|
||||||
x; //~ ERROR use of moved value: `x`
|
true => drop(x), //~ ERROR use of moved value: `x`
|
||||||
2
|
false => {},
|
||||||
}
|
};
|
||||||
false => 3,
|
|
||||||
|
// Fine in the other order.
|
||||||
|
let x = String::new();
|
||||||
|
match y {
|
||||||
|
true => drop(x),
|
||||||
|
false if { drop(x); true } => {},
|
||||||
|
false => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
let x = String::new();
|
let x = String::new();
|
||||||
match y {
|
match y {
|
||||||
false if let Some(()) = { drop(x); Some(()) } => 1,
|
false if let Some(()) = { drop(x); Some(()) } => {},
|
||||||
true => {
|
true => drop(x), //~ ERROR use of moved value: `x`
|
||||||
x; //~ ERROR use of moved value: `x`
|
false => {},
|
||||||
2
|
|
||||||
}
|
|
||||||
false => 3,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,72 @@
|
||||||
error[E0381]: used binding `x` isn't initialized
|
error[E0382]: use of moved value: `x`
|
||||||
--> $DIR/match-cfg-fake-edges.rs:29:13
|
--> $DIR/match-cfg-fake-edges.rs:16:10
|
||||||
|
|
|
||||||
|
LL | let x = String::new();
|
||||||
|
| - move occurs because `x` has type `String`, which does not implement the `Copy` trait
|
||||||
|
...
|
||||||
|
LL | _ => drop(x),
|
||||||
|
| - value moved here
|
||||||
|
...
|
||||||
|
LL | drop(x);
|
||||||
|
| ^ value used here after move
|
||||||
|
|
|
||||||
|
help: consider cloning the value if the performance cost is acceptable
|
||||||
|
|
|
||||||
|
LL | _ => drop(x.clone()),
|
||||||
|
| ++++++++
|
||||||
|
|
||||||
|
error[E0382]: borrow of moved value: `x.0`
|
||||||
|
--> $DIR/match-cfg-fake-edges.rs:22:5
|
||||||
|
|
|
||||||
|
LL | (y, _) | (_, y) => (),
|
||||||
|
| - value moved here
|
||||||
|
LL | }
|
||||||
|
LL | &x.0;
|
||||||
|
| ^^^^ value borrowed here after move
|
||||||
|
|
|
||||||
|
= note: move occurs because `x.0` has type `String`, which does not implement the `Copy` trait
|
||||||
|
help: borrow this binding in the pattern to avoid moving the value
|
||||||
|
|
|
||||||
|
LL | (ref y, _) | (_, y) => (),
|
||||||
|
| +++
|
||||||
|
|
||||||
|
error[E0382]: borrow of moved value: `x.1`
|
||||||
|
--> $DIR/match-cfg-fake-edges.rs:24:5
|
||||||
|
|
|
||||||
|
LL | (y, _) | (_, y) => (),
|
||||||
|
| - value moved here
|
||||||
|
...
|
||||||
|
LL | &x.1;
|
||||||
|
| ^^^^ value borrowed here after move
|
||||||
|
|
|
||||||
|
= note: move occurs because `x.1` has type `String`, which does not implement the `Copy` trait
|
||||||
|
help: borrow this binding in the pattern to avoid moving the value
|
||||||
|
|
|
||||||
|
LL | (y, _) | (_, ref y) => (),
|
||||||
|
| +++
|
||||||
|
|
||||||
|
error[E0381]: used binding `x` is possibly-uninitialized
|
||||||
|
--> $DIR/match-cfg-fake-edges.rs:58:19
|
||||||
|
|
|
|
||||||
LL | let x;
|
LL | let x;
|
||||||
| - binding declared here but left uninitialized
|
| - binding declared here but left uninitialized
|
||||||
...
|
...
|
||||||
|
LL | _ => drop(x),
|
||||||
|
| - ^ `x` used here but it is possibly-uninitialized
|
||||||
|
| |
|
||||||
|
| if this pattern is matched, `x` is not initialized
|
||||||
|
|
||||||
|
error[E0381]: used binding `x` isn't initialized
|
||||||
|
--> $DIR/match-cfg-fake-edges.rs:65:16
|
||||||
|
|
|
||||||
|
LL | let x;
|
||||||
|
| - binding declared here but left uninitialized
|
||||||
|
LL | match y {
|
||||||
LL | _ if { x = 2; true } => 1,
|
LL | _ if { x = 2; true } => 1,
|
||||||
| ----- binding initialized here in some conditions
|
| ----- binding initialized here in some conditions
|
||||||
LL | _ if {
|
LL | // Borrowck must not know the guard is always run.
|
||||||
LL | x;
|
LL | _ if { x; false } => 2,
|
||||||
| ^ `x` used here but it isn't initialized
|
| ^ `x` used here but it isn't initialized
|
||||||
|
|
|
|
||||||
help: consider assigning a value
|
help: consider assigning a value
|
||||||
|
|
|
|
||||||
|
@ -16,16 +74,15 @@ LL | let x = 0;
|
||||||
| +++
|
| +++
|
||||||
|
|
||||||
error[E0381]: used binding `x` isn't initialized
|
error[E0381]: used binding `x` isn't initialized
|
||||||
--> $DIR/match-cfg-fake-edges.rs:39:13
|
--> $DIR/match-cfg-fake-edges.rs:72:31
|
||||||
|
|
|
|
||||||
LL | let x;
|
LL | let x;
|
||||||
| - binding declared here but left uninitialized
|
| - binding declared here but left uninitialized
|
||||||
LL | match y {
|
LL | match y {
|
||||||
LL | _ if let Some(()) = { x = 2; Some(()) } => 1,
|
LL | _ if let Some(()) = { x = 2; Some(()) } => 1,
|
||||||
| ----- binding initialized here in some conditions
|
| ----- binding initialized here in some conditions
|
||||||
LL | _ if let Some(()) = {
|
LL | _ if let Some(()) = { x; None } => 2,
|
||||||
LL | x;
|
| ^ `x` used here but it isn't initialized
|
||||||
| ^ `x` used here but it isn't initialized
|
|
||||||
|
|
|
|
||||||
help: consider assigning a value
|
help: consider assigning a value
|
||||||
|
|
|
|
||||||
|
@ -33,40 +90,39 @@ LL | let x = 0;
|
||||||
| +++
|
| +++
|
||||||
|
|
||||||
error[E0382]: use of moved value: `x`
|
error[E0382]: use of moved value: `x`
|
||||||
--> $DIR/match-cfg-fake-edges.rs:53:13
|
--> $DIR/match-cfg-fake-edges.rs:85:22
|
||||||
|
|
|
||||||
LL | let x = String::new();
|
|
||||||
| - move occurs because `x` has type `String`, which does not implement the `Copy` trait
|
|
||||||
...
|
|
||||||
LL | false if { drop(x); true } => 1,
|
|
||||||
| - value moved here
|
|
||||||
LL | true => {
|
|
||||||
LL | x;
|
|
||||||
| ^ value used here after move
|
|
||||||
|
|
|
||||||
help: consider cloning the value if the performance cost is acceptable
|
|
||||||
|
|
|
||||||
LL | false if { drop(x.clone()); true } => 1,
|
|
||||||
| ++++++++
|
|
||||||
|
|
||||||
error[E0382]: use of moved value: `x`
|
|
||||||
--> $DIR/match-cfg-fake-edges.rs:63:13
|
|
||||||
|
|
|
|
||||||
LL | let x = String::new();
|
LL | let x = String::new();
|
||||||
| - move occurs because `x` has type `String`, which does not implement the `Copy` trait
|
| - move occurs because `x` has type `String`, which does not implement the `Copy` trait
|
||||||
LL | match y {
|
LL | match y {
|
||||||
LL | false if let Some(()) = { drop(x); Some(()) } => 1,
|
LL | false if { drop(x); true } => {},
|
||||||
| - value moved here
|
| - value moved here
|
||||||
LL | true => {
|
LL | // Borrowck must not know the guard is not run in the `true` case.
|
||||||
LL | x;
|
LL | true => drop(x),
|
||||||
| ^ value used here after move
|
| ^ value used here after move
|
||||||
|
|
|
|
||||||
help: consider cloning the value if the performance cost is acceptable
|
help: consider cloning the value if the performance cost is acceptable
|
||||||
|
|
|
|
||||||
LL | false if let Some(()) = { drop(x.clone()); Some(()) } => 1,
|
LL | false if { drop(x.clone()); true } => {},
|
||||||
|
| ++++++++
|
||||||
|
|
||||||
|
error[E0382]: use of moved value: `x`
|
||||||
|
--> $DIR/match-cfg-fake-edges.rs:100:22
|
||||||
|
|
|
||||||
|
LL | let x = String::new();
|
||||||
|
| - move occurs because `x` has type `String`, which does not implement the `Copy` trait
|
||||||
|
LL | match y {
|
||||||
|
LL | false if let Some(()) = { drop(x); Some(()) } => {},
|
||||||
|
| - value moved here
|
||||||
|
LL | true => drop(x),
|
||||||
|
| ^ value used here after move
|
||||||
|
|
|
||||||
|
help: consider cloning the value if the performance cost is acceptable
|
||||||
|
|
|
||||||
|
LL | false if let Some(()) = { drop(x.clone()); Some(()) } => {},
|
||||||
| ++++++++
|
| ++++++++
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 8 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0381, E0382.
|
Some errors have detailed explanations: E0381, E0382.
|
||||||
For more information about an error, try `rustc --explain E0381`.
|
For more information about an error, try `rustc --explain E0381`.
|
||||||
|
|
|
@ -5,13 +5,20 @@ fn all_previous_tests_may_be_done(y: &mut (bool, bool)) {
|
||||||
let r = &mut y.1;
|
let r = &mut y.1;
|
||||||
// We don't actually test y.1 to select the second arm, but we don't want
|
// 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.
|
// borrowck results to be based on the order we match patterns.
|
||||||
match y { //~ ERROR cannot use `y.1` because it was mutably borrowed
|
match y {
|
||||||
(false, true) => 1,
|
//~^ ERROR cannot use `y.1` because it was mutably borrowed
|
||||||
(true, _) => {
|
(false, true) => {}
|
||||||
r;
|
// Borrowck must not know we don't test `y.1` when `y.0` is `true`.
|
||||||
2
|
(true, _) => drop(r),
|
||||||
}
|
(false, _) => {}
|
||||||
(false, _) => 3,
|
};
|
||||||
|
|
||||||
|
// Fine in the other order.
|
||||||
|
let r = &mut y.1;
|
||||||
|
match y {
|
||||||
|
(true, _) => drop(r),
|
||||||
|
(false, true) => {}
|
||||||
|
(false, _) => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,8 @@ LL | let r = &mut y.1;
|
||||||
LL | match y {
|
LL | match y {
|
||||||
| ^^^^^^^ use of borrowed `y.1`
|
| ^^^^^^^ use of borrowed `y.1`
|
||||||
...
|
...
|
||||||
LL | r;
|
LL | (true, _) => drop(r),
|
||||||
| - borrow later used here
|
| - borrow later used here
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue