about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNadrieril <nadrieril+git@gmail.com>2024-03-10 14:15:03 +0100
committerNadrieril <nadrieril+git@gmail.com>2024-04-03 21:02:47 +0200
commit50103ab14d678c1c04a3db5621072bb1f8c2d860 (patch)
treedfb77d984bf28a2766fed4188ec4a85a25bcd855
parentceab6128fa48a616bfd3e3adf4bc80133b8ee223 (diff)
downloadrust-50103ab14d678c1c04a3db5621072bb1f8c2d860.tar.gz
rust-50103ab14d678c1c04a3db5621072bb1f8c2d860.zip
Add tests
-rw-r--r--tests/ui/nll/match-cfg-fake-edges.rs83
-rw-r--r--tests/ui/nll/match-cfg-fake-edges.stderr102
-rw-r--r--tests/ui/nll/match-cfg-fake-edges2.rs21
-rw-r--r--tests/ui/nll/match-cfg-fake-edges2.stderr4
4 files changed, 154 insertions, 56 deletions
diff --git a/tests/ui/nll/match-cfg-fake-edges.rs b/tests/ui/nll/match-cfg-fake-edges.rs
index 1afc7931a6b..e2ba164684f 100644
--- a/tests/ui/nll/match-cfg-fake-edges.rs
+++ b/tests/ui/nll/match-cfg-fake-edges.rs
@@ -3,10 +3,32 @@
 
 #![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,
@@ -14,56 +36,69 @@ fn guard_always_precedes_arm(y: i32) {
 
     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 => {},
     };
 }
 
diff --git a/tests/ui/nll/match-cfg-fake-edges.stderr b/tests/ui/nll/match-cfg-fake-edges.stderr
index a6261345cea..2f79c073247 100644
--- a/tests/ui/nll/match-cfg-fake-edges.stderr
+++ b/tests/ui/nll/match-cfg-fake-edges.stderr
@@ -1,14 +1,72 @@
-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
    |
@@ -16,16 +74,15 @@ 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
    |
@@ -33,40 +90,39 @@ 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`.
diff --git a/tests/ui/nll/match-cfg-fake-edges2.rs b/tests/ui/nll/match-cfg-fake-edges2.rs
index 48f95e03b78..ac90fb9cd1e 100644
--- a/tests/ui/nll/match-cfg-fake-edges2.rs
+++ b/tests/ui/nll/match-cfg-fake-edges2.rs
@@ -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, _) => {}
     };
 }
 
diff --git a/tests/ui/nll/match-cfg-fake-edges2.stderr b/tests/ui/nll/match-cfg-fake-edges2.stderr
index 639cba1406a..0a228d62b92 100644
--- a/tests/ui/nll/match-cfg-fake-edges2.stderr
+++ b/tests/ui/nll/match-cfg-fake-edges2.stderr
@@ -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