about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/usefulness.rs3
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/omitted-patterns.rs16
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr17
3 files changed, 35 insertions, 1 deletions
diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
index be66d0d4765..9edd7967e7a 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
@@ -300,6 +300,7 @@ use rustc_arena::TypedArena;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir::def_id::DefId;
 use rustc_hir::HirId;
+use rustc_hir::Node;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
 use rustc_span::{Span, DUMMY_SP};
@@ -867,6 +868,8 @@ fn is_useful<'p, 'tcx>(
                     &ctor,
                     Constructor::Missing { nonexhaustive_enum_missing_real_variants: true }
                 )
+                // We don't want to lint patterns which are function arguments or locals
+                && !matches!(cx.tcx.hir().find_parent(hir_id), Some(Node::Param(_)|Node::Local(_)))
             {
                 let patterns = {
                     let mut split_wildcard = SplitWildcard::new(pcx);
diff --git a/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.rs b/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.rs
index d8f07bb8f24..7ef1d635d9c 100644
--- a/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.rs
+++ b/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.rs
@@ -184,4 +184,20 @@ fn main() {
     // OK: both unstable and stable fields are matched with feature on
     #[warn(non_exhaustive_omitted_patterns)]
     let UnstableStruct { stable, stable2, unstable, .. } = UnstableStruct::default();
+
+    // Ok: local bindings are allowed
+    #[deny(non_exhaustive_omitted_patterns)]
+    let local = NonExhaustiveEnum::Unit;
+
+    // Ok: missing patterns will be blocked by the pattern being refutable
+    #[deny(non_exhaustive_omitted_patterns)]
+    let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit;
+    //~^ refutable pattern in local binding
+
+}
+
+#[deny(non_exhaustive_omitted_patterns)]
+// Ok: Pattern in a param is always wildcard
+pub fn takes_non_exhaustive(_: NonExhaustiveEnum) {
+    let _closure = |_: NonExhaustiveEnum| {};
 }
diff --git a/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr b/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr
index 996bd4a1298..617c629a4fe 100644
--- a/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr
+++ b/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr
@@ -184,5 +184,20 @@ note: the lint level is defined here
 LL |     #[deny(non_exhaustive_omitted_patterns)]
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 8 previous errors; 6 warnings emitted
+error[E0005]: refutable pattern in local binding
+  --> $DIR/omitted-patterns.rs:194:9
+   |
+LL |     let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `_` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+   = note: the matched value is of type `NonExhaustiveEnum`
+help: you might want to use `let else` to handle the variant that isn't matched
+   |
+LL |     let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit else { todo!() };
+   |                                                                             ++++++++++++++++
+
+error: aborting due to 9 previous errors; 6 warnings emitted
 
+For more information about this error, try `rustc --explain E0005`.