| // Test that we have enough false edges to avoid exposing the exact matching |
| // algorithm in borrow checking. |
| |
| #![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(); |
| 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(); |
| if let _ = true { //~ WARN irrefutable |
| } else { |
| drop(x) |
| } |
| // Borrowck must not know the else branch 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 |
| |
| let x = (String::new(), String::new()); |
| let ((y, _) | (_, y)) = x; |
| &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) { |
| // 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; |
| match y { |
| _ if { x = 2; true } => 1, |
| // 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; None } => 2, //~ ERROR used binding `x` isn't initialized |
| _ => 3, |
| }; |
| } |
| |
| #[rustfmt::skip] |
| fn guard_may_be_taken(y: bool) { |
| // 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 { |
| true => drop(x), |
| false if { drop(x); true } => {}, |
| false => {}, |
| }; |
| |
| let x = String::new(); |
| match y { |
| false if let Some(()) = { drop(x); Some(()) } => {}, |
| true => drop(x), //~ ERROR use of moved value: `x` |
| false => {}, |
| }; |
| } |
| |
| fn main() {} |