Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Nadrieril committed Apr 3, 2024
1 parent ceab612 commit 50103ab
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 56 deletions.
83 changes: 59 additions & 24 deletions tests/ui/nll/match-cfg-fake-edges.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,67 +3,102 @@

#![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) {
let mut x;
// x should always be initialized, as the only way to reach the arm is
// through the guard.
let mut x;
match y {
0 | 2 if { x = 2; true } => x,
_ => 2,
};

let mut x;
match y {
_ => 2,
0 | 2 if { x = 2; true } => x,
};

let mut x;
match y {
0 | 2 if let Some(()) = { x = 2; Some(()) } => x,
_ => 2,
};
}

#[rustfmt::skip]
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;
// 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 E0381
false
} => 2,
// Borrowck must not know the guard is always run.
_ if { x; false } => 2, //~ ERROR used binding `x` isn't initialized
_ => 3,
};

let x;
match y {
_ if let Some(()) = { x = 2; Some(()) } => 1,
_ if let Some(()) = {
x; //~ ERROR E0381
None
} => 2,
_ if let Some(()) = { x; None } => 2, //~ ERROR used binding `x` isn't initialized
_ => 3,
};
}

#[rustfmt::skip]
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.
let x = String::new();
match y {
false if { drop(x); true } => {},
// Borrowck must not know the guard is not run in the `true` case.
true => drop(x), //~ ERROR use of moved value: `x`
false => {},
};

// Fine in the other order.
let x = String::new();
match y {
false if { drop(x); true } => 1,
true => {
x; //~ ERROR use of moved value: `x`
2
}
false => 3,
true => drop(x),
false if { drop(x); true } => {},
false => {},
};

let x = String::new();
match y {
false if let Some(()) = { drop(x); Some(()) } => 1,
true => {
x; //~ ERROR use of moved value: `x`
2
}
false => 3,
false if let Some(()) = { drop(x); Some(()) } => {},
true => drop(x), //~ ERROR use of moved value: `x`
false => {},
};
}

Expand Down
102 changes: 79 additions & 23 deletions tests/ui/nll/match-cfg-fake-edges.stderr
Original file line number Diff line number Diff line change
@@ -1,72 +1,128 @@
error[E0381]: used binding `x` isn't initialized
--> $DIR/match-cfg-fake-edges.rs:29:13
error[E0382]: use of moved value: `x`
--> $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;
| - 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,
| ----- binding initialized here in some conditions
LL | _ if {
LL | x;
| ^ `x` used here but it isn't initialized
LL | // Borrowck must not know the guard is always run.
LL | _ if { x; false } => 2,
| ^ `x` used here but it isn't initialized
|
help: consider assigning a value
|
LL | let x = 0;
| +++

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;
| - binding declared here but left uninitialized
LL | match y {
LL | _ if let Some(()) = { x = 2; Some(()) } => 1,
| ----- binding initialized here in some conditions
LL | _ if let Some(()) = {
LL | x;
| ^ `x` used here but it isn't initialized
LL | _ if let Some(()) = { x; None } => 2,
| ^ `x` used here but it isn't initialized
|
help: consider assigning a value
|
LL | let x = 0;
| +++

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,
LL | match y {
LL | false if { drop(x); true } => {},
| - value moved here
LL | true => {
LL | x;
| ^ value used here after move
LL | // Borrowck must not know the guard is not run in the `true` case.
LL | true => drop(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,
LL | false if { drop(x.clone()); true } => {},
| ++++++++

error[E0382]: use of moved value: `x`
--> $DIR/match-cfg-fake-edges.rs:63:13
--> $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(()) } => 1,
LL | false if let Some(()) = { drop(x); Some(()) } => {},
| - value moved here
LL | true => {
LL | x;
| ^ value used here after move
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(()) } => 1,
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.
For more information about an error, try `rustc --explain E0381`.
21 changes: 14 additions & 7 deletions tests/ui/nll/match-cfg-fake-edges2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,20 @@ 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 { //~ ERROR cannot use `y.1` because it was mutably borrowed
(false, true) => 1,
(true, _) => {
r;
2
}
(false, _) => 3,
match y {
//~^ ERROR cannot use `y.1` because it was mutably borrowed
(false, true) => {}
// Borrowck must not know we don't test `y.1` when `y.0` is `true`.
(true, _) => drop(r),
(false, _) => {}
};

// Fine in the other order.
let r = &mut y.1;
match y {
(true, _) => drop(r),
(false, true) => {}
(false, _) => {}
};
}

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/nll/match-cfg-fake-edges2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ LL | let r = &mut y.1;
LL | match y {
| ^^^^^^^ use of borrowed `y.1`
...
LL | r;
| - borrow later used here
LL | (true, _) => drop(r),
| - borrow later used here

error: aborting due to 1 previous error

Expand Down

0 comments on commit 50103ab

Please sign in to comment.