about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_typeck/src/expr_use_visitor.rs19
-rw-r--r--src/test/ui/closures/2229_closure_analysis/match/auxiliary/match_non_exhaustive_lib.rs10
-rw-r--r--src/test/ui/closures/2229_closure_analysis/match/issue-87097.rs (renamed from src/test/ui/closures/2229_closure_analysis/issue-87097.rs)0
-rw-r--r--src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr (renamed from src/test/ui/closures/2229_closure_analysis/issue-87097.stderr)0
-rw-r--r--src/test/ui/closures/2229_closure_analysis/match/issue-87426.rs (renamed from src/test/ui/closures/2229_closure_analysis/issue-87426.rs)0
-rw-r--r--src/test/ui/closures/2229_closure_analysis/match/issue-87988.rs (renamed from src/test/ui/closures/2229_closure_analysis/issue-87988.rs)0
-rw-r--r--src/test/ui/closures/2229_closure_analysis/match/issue-88331.rs (renamed from src/test/ui/closures/2229_closure_analysis/issue-88331.rs)0
-rw-r--r--src/test/ui/closures/2229_closure_analysis/match/issue-88331.stderr (renamed from src/test/ui/closures/2229_closure_analysis/issue-88331.stderr)0
-rw-r--r--src/test/ui/closures/2229_closure_analysis/match/match-edge-cases_1.rs (renamed from src/test/ui/closures/2229_closure_analysis/match-edge-cases.rs)0
-rw-r--r--src/test/ui/closures/2229_closure_analysis/match/match-edge-cases_2.rs37
-rw-r--r--src/test/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr17
-rw-r--r--src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs54
-rw-r--r--src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr50
-rw-r--r--src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.rs (renamed from src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.rs)0
-rw-r--r--src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr (renamed from src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.stderr)0
-rw-r--r--src/test/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs (renamed from src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.rs)0
-rw-r--r--src/test/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr (renamed from src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.stderr)0
17 files changed, 185 insertions, 2 deletions
diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs
index a8be207dbb3..3d483e322a8 100644
--- a/compiler/rustc_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_typeck/src/expr_use_visitor.rs
@@ -15,7 +15,7 @@ use rustc_index::vec::Idx;
 use rustc_infer::infer::InferCtxt;
 use rustc_middle::hir::place::ProjectionKind;
 use rustc_middle::mir::FakeReadCause;
-use rustc_middle::ty::{self, adjustment, Ty, TyCtxt};
+use rustc_middle::ty::{self, adjustment, AdtKind, Ty, TyCtxt};
 use rustc_target::abi::VariantIdx;
 use std::iter;
 
@@ -845,5 +845,20 @@ fn delegate_consume<'a, 'tcx>(
 }
 
 fn is_multivariant_adt(ty: Ty<'tcx>) -> bool {
-    if let ty::Adt(def, _) = ty.kind() { def.variants.len() > 1 } else { false }
+    if let ty::Adt(def, _) = ty.kind() {
+        // Note that if a non-exhaustive SingleVariant is defined in another crate, we need
+        // to assume that more cases will be added to the variant in the future. This mean
+        // that we should handle non-exhaustive SingleVariant the same way we would handle
+        // a MultiVariant.
+        // If the variant is not local it must be defined in another crate.
+        let is_non_exhaustive = match def.adt_kind() {
+            AdtKind::Struct | AdtKind::Union => {
+                def.non_enum_variant().is_field_list_non_exhaustive()
+            }
+            AdtKind::Enum => def.is_variant_list_non_exhaustive(),
+        };
+        def.variants.len() > 1 || (!def.did.is_local() && is_non_exhaustive)
+    } else {
+        false
+    }
 }
diff --git a/src/test/ui/closures/2229_closure_analysis/match/auxiliary/match_non_exhaustive_lib.rs b/src/test/ui/closures/2229_closure_analysis/match/auxiliary/match_non_exhaustive_lib.rs
new file mode 100644
index 00000000000..4060c409355
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/match/auxiliary/match_non_exhaustive_lib.rs
@@ -0,0 +1,10 @@
+#[non_exhaustive]
+pub enum E1 {}
+
+#[non_exhaustive]
+pub enum E2 { A, B }
+
+#[non_exhaustive]
+pub enum E3 { C }
+
+pub enum E4 { D }
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87097.rs b/src/test/ui/closures/2229_closure_analysis/match/issue-87097.rs
index 241ddcb83e1..241ddcb83e1 100644
--- a/src/test/ui/closures/2229_closure_analysis/issue-87097.rs
+++ b/src/test/ui/closures/2229_closure_analysis/match/issue-87097.rs
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87097.stderr b/src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr
index 38f2929a05f..38f2929a05f 100644
--- a/src/test/ui/closures/2229_closure_analysis/issue-87097.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87426.rs b/src/test/ui/closures/2229_closure_analysis/match/issue-87426.rs
index 74506979a28..74506979a28 100644
--- a/src/test/ui/closures/2229_closure_analysis/issue-87426.rs
+++ b/src/test/ui/closures/2229_closure_analysis/match/issue-87426.rs
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87988.rs b/src/test/ui/closures/2229_closure_analysis/match/issue-87988.rs
index 27e7fabf11a..27e7fabf11a 100644
--- a/src/test/ui/closures/2229_closure_analysis/issue-87988.rs
+++ b/src/test/ui/closures/2229_closure_analysis/match/issue-87988.rs
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-88331.rs b/src/test/ui/closures/2229_closure_analysis/match/issue-88331.rs
index 0a6d71c68ae..0a6d71c68ae 100644
--- a/src/test/ui/closures/2229_closure_analysis/issue-88331.rs
+++ b/src/test/ui/closures/2229_closure_analysis/match/issue-88331.rs
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-88331.stderr b/src/test/ui/closures/2229_closure_analysis/match/issue-88331.stderr
index f02d23464f1..f02d23464f1 100644
--- a/src/test/ui/closures/2229_closure_analysis/issue-88331.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/match/issue-88331.stderr
diff --git a/src/test/ui/closures/2229_closure_analysis/match-edge-cases.rs b/src/test/ui/closures/2229_closure_analysis/match/match-edge-cases_1.rs
index 914ebbe26a5..914ebbe26a5 100644
--- a/src/test/ui/closures/2229_closure_analysis/match-edge-cases.rs
+++ b/src/test/ui/closures/2229_closure_analysis/match/match-edge-cases_1.rs
diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-edge-cases_2.rs b/src/test/ui/closures/2229_closure_analysis/match/match-edge-cases_2.rs
new file mode 100644
index 00000000000..ae724f9c3cc
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/match/match-edge-cases_2.rs
@@ -0,0 +1,37 @@
+// edition:2021
+
+enum SingleVariant {
+    A
+}
+
+struct TestStruct {
+    x: i32,
+    y: i32,
+    z: i32,
+}
+
+fn edge_case_if() {
+    let sv = SingleVariant::A;
+    let condition = true;
+    // sv should not be captured as it is a SingleVariant
+    let _a = || {
+        match sv {
+            SingleVariant::A if condition => (),
+            _ => ()
+        }
+    };
+    let mut mut_sv = sv;
+    _a();
+
+    // ts should be captured
+    let ts = TestStruct { x: 1, y: 1, z: 1 };
+    let _b = || { match ts {
+        TestStruct{ x: 1, .. } => (),
+        _ => ()
+    }};
+    let mut mut_ts = ts;
+    //~^ ERROR: cannot move out of `ts` because it is borrowed
+    _b();
+}
+
+fn main() {}
diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr
new file mode 100644
index 00000000000..1e42d73c62b
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr
@@ -0,0 +1,17 @@
+error[E0505]: cannot move out of `ts` because it is borrowed
+  --> $DIR/match-edge-cases_2.rs:32:22
+   |
+LL |     let _b = || { match ts {
+   |              --         -- borrow occurs due to use in closure
+   |              |
+   |              borrow of `ts` occurs here
+...
+LL |     let mut mut_ts = ts;
+   |                      ^^ move out of `ts` occurs here
+LL |
+LL |     _b();
+   |     -- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs b/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs
new file mode 100644
index 00000000000..318673ef847
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs
@@ -0,0 +1,54 @@
+// edition:2021
+
+// aux-build:match_non_exhaustive_lib.rs
+
+/* The error message for non-exhaustive matches on non-local enums
+ * marked as non-exhaustive should mention the fact that the enum
+ * is marked as non-exhaustive (issue #85227).
+ */
+
+// Ignore non_exhaustive in the same crate
+#[non_exhaustive]
+enum L1 { A, B }
+enum L2 { C }
+
+extern crate match_non_exhaustive_lib;
+use match_non_exhaustive_lib::{E1, E2, E3, E4};
+
+fn foo() -> (L1, L2) {todo!()}
+fn bar() -> (E1, E2, E3, E4) {todo!()}
+
+fn main() {
+    let (l1, l2) = foo();
+    // No error for enums defined in this crate
+    let _a = || { match l1 { L1::A => (), L1::B => () } };
+    // (except if the match is already non-exhaustive)
+    let _b = || { match l1 { L1::A => () } };
+    //~^ ERROR: non-exhaustive patterns: `B` not covered [E0004]
+
+    // l2 should not be captured as it is a non-exhaustive SingleVariant
+    // defined in this crate
+    let _c = || { match l2 { L2::C => (), _ => () }  };
+    let mut mut_l2 = l2;
+    _c();
+
+    // E1 is not visibly uninhabited from here
+    let (e1, e2, e3, e4) = bar();
+    let _d = || { match e1 {} };
+    //~^ ERROR: non-exhaustive patterns: type `E1` is non-empty [E0004]
+    let _e = || { match e2 { E2::A => (), E2::B => () } };
+    //~^ ERROR: non-exhaustive patterns: `_` not covered [E0004]
+    let _f = || { match e2 { E2::A => (), E2::B => (), _ => () }  };
+
+    // e3 should be captured as it is a non-exhaustive SingleVariant
+    // defined in another crate
+    let _g = || { match e3 { E3::C => (), _ => () }  };
+    let mut mut_e3 = e3;
+    //~^ ERROR: cannot move out of `e3` because it is borrowed
+    _g();
+
+    // e4 should not be captured as it is a SingleVariant
+    let _h = || { match e4 { E4::D => (), _ => () }  };
+    let mut mut_e4 = e4;
+    _h();
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr b/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr
new file mode 100644
index 00000000000..91ffe1a47f4
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr
@@ -0,0 +1,50 @@
+error[E0004]: non-exhaustive patterns: `B` not covered
+  --> $DIR/non-exhaustive-match.rs:26:25
+   |
+LL | enum L1 { A, B }
+   | ----------------
+   | |            |
+   | |            not covered
+   | `L1` defined here
+...
+LL |     let _b = || { match l1 { L1::A => () } };
+   |                         ^^ pattern `B` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `L1`
+
+error[E0004]: non-exhaustive patterns: type `E1` is non-empty
+  --> $DIR/non-exhaustive-match.rs:37:25
+   |
+LL |     let _d = || { match e1 {} };
+   |                         ^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `E1`, which is marked as non-exhaustive
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/non-exhaustive-match.rs:39:25
+   |
+LL |     let _e = || { match e2 { E2::A => (), E2::B => () } };
+   |                         ^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `E2`, which is marked as non-exhaustive
+
+error[E0505]: cannot move out of `e3` because it is borrowed
+  --> $DIR/non-exhaustive-match.rs:46:22
+   |
+LL |     let _g = || { match e3 { E3::C => (), _ => () }  };
+   |              --         -- borrow occurs due to use in closure
+   |              |
+   |              borrow of `e3` occurs here
+LL |     let mut mut_e3 = e3;
+   |                      ^^ move out of `e3` occurs here
+LL |
+LL |     _g();
+   |     -- borrow later used here
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0004, E0505.
+For more information about an error, try `rustc --explain E0004`.
diff --git a/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.rs b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.rs
index 0f288ffa95a..0f288ffa95a 100644
--- a/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.rs
+++ b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.rs
diff --git a/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.stderr b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr
index 45641ea3de3..45641ea3de3 100644
--- a/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr
diff --git a/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.rs b/src/test/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs
index 56f5ac44db0..56f5ac44db0 100644
--- a/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.rs
+++ b/src/test/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs
diff --git a/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.stderr b/src/test/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr
index 46081333395..46081333395 100644
--- a/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr