about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2019-02-10 05:12:00 -0800
committerEsteban Küber <esteban@kuber.com.ar>2019-03-02 16:45:23 -0800
commit0081ef2548f95171b33bbaedcd90253cf41916b2 (patch)
tree274d2b7674db77cb6abcd489c5bd69d767e77ca1
parentc1d2d83ca3b5155468ab96b09a7c54568449b137 (diff)
downloadrust-0081ef2548f95171b33bbaedcd90253cf41916b2.tar.gz
rust-0081ef2548f95171b33bbaedcd90253cf41916b2.zip
Point at enum definition when match patterns are not exhaustive
```
error[E0004]: non-exhaustive patterns: type `X` is non-empty
 --> file.rs:9:11
  |
1 | / enum X {
2 | |     A,
  | |     - variant not covered
3 | |     B,
  | |     - variant not covered
4 | |     C,
  | |     - variant not covered
5 | | }
  | |_- `X` defined here
...
9 |       match x {
  |             ^
  |
  = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

error[E0004]: non-exhaustive patterns: `B` and `C` not covered
  --> file.rs:11:11
   |
1  | / enum X {
2  | |     A,
3  | |     B,
4  | |     C,
   | |     - not covered
5  | | }
   | |_- `X` defined here
...
11 |       match x {
   |             ^ patterns `C` not covered
```

When a match expression doesn't have patterns covering every variant,
point at the enum's definition span. On a best effort basis, point at the
variant(s) that are missing. This does not handle the case when the missing
pattern is due to a field's enum variants:

```
enum E1 {
    A,
    B,
    C,
}
enum E2 {
    A(E1),
    B,
}
fn foo() {
    match E2::A(E1::A) {
        E2::A(E1::B) => {}
        E2::B => {}
    }
    //~^ ERROR `E2::A(E1::A)` and `E2::A(E1::C)` not handled
}
```

Unify look between match with no arms and match with some missing patterns.

Fix #37518.
-rw-r--r--src/librustc_mir/hair/pattern/_match.rs1
-rw-r--r--src/librustc_mir/hair/pattern/check_match.rs134
-rw-r--r--src/test/ui/always-inhabited-union-ref.stderr12
-rw-r--r--src/test/ui/check_match/issue-35609.stderr22
-rw-r--r--src/test/ui/consts/match_ice.stderr2
-rw-r--r--src/test/ui/empty/empty-never-array.stderr11
-rw-r--r--src/test/ui/error-codes/E0004-2.stderr6
-rw-r--r--src/test/ui/error-codes/E0004.stderr13
-rw-r--r--src/test/ui/exhaustive_integer_patterns.stderr22
-rw-r--r--src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr4
-rw-r--r--src/test/ui/issues/issue-15129.stderr2
-rw-r--r--src/test/ui/issues/issue-2111.stderr2
-rw-r--r--src/test/ui/issues/issue-30240.stderr4
-rw-r--r--src/test/ui/issues/issue-3096-1.stderr6
-rw-r--r--src/test/ui/issues/issue-3096-2.stderr6
-rw-r--r--src/test/ui/issues/issue-31561.stderr11
-rw-r--r--src/test/ui/issues/issue-3601.stderr2
-rw-r--r--src/test/ui/issues/issue-39362.stderr11
-rw-r--r--src/test/ui/issues/issue-4321.stderr2
-rw-r--r--src/test/ui/match/match-argm-statics-2.stderr16
-rw-r--r--src/test/ui/match/match-byte-array-patterns-2.stderr4
-rw-r--r--src/test/ui/match/match-non-exhaustive.stderr4
-rw-r--r--src/test/ui/match/match-privately-empty.stderr2
-rw-r--r--src/test/ui/match/match-slice-patterns.stderr2
-rw-r--r--src/test/ui/missing/missing-items/issue-40221.stderr12
-rw-r--r--src/test/ui/non-exhaustive/non-exhaustive-float-range-match.stderr2
-rw-r--r--src/test/ui/non-exhaustive/non-exhaustive-match-nested.stderr10
-rw-r--r--src/test/ui/non-exhaustive/non-exhaustive-match.stderr28
-rw-r--r--src/test/ui/non-exhaustive/non-exhaustive-pattern-witness.stderr70
-rw-r--r--src/test/ui/precise_pointer_size_matching.stderr4
-rw-r--r--src/test/ui/rfc-2005-default-binding-mode/slice.stderr2
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/enum.stderr2
-rw-r--r--src/test/ui/structs/struct-like-enum-nonexhaustive.stderr13
-rw-r--r--src/test/ui/tuple/tuple-struct-nonexhaustive.stderr5
-rw-r--r--src/test/ui/uninhabited/uninhabited-irrefutable.stderr12
-rw-r--r--src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr24
36 files changed, 390 insertions, 95 deletions
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 9e9a5d0f82a..60eb30e0753 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -539,7 +539,6 @@ impl<'tcx> Witness<'tcx> {
         self.apply_constructor(cx, ctor, ty)
     }
 
-
     /// Constructs a partial witness for a pattern given a list of
     /// patterns expanded by the specialization step.
     ///
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index 0f151cd688d..96709e2ac04 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -10,7 +10,7 @@ use rustc::middle::expr_use_visitor as euv;
 use rustc::middle::mem_categorization::cmt_;
 use rustc::middle::region;
 use rustc::session::Session;
-use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::{self, Ty, TyCtxt, TyKind};
 use rustc::ty::subst::{InternalSubsts, SubstsRef};
 use rustc::lint;
 use rustc_errors::{Applicability, DiagnosticBuilder};
@@ -204,25 +204,42 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
             // is uninhabited.
             let pat_ty = self.tables.node_type(scrut.hir_id);
             let module = self.tcx.hir().get_module_parent_by_hir_id(scrut.hir_id);
+            let mut def_span = None;
+            let mut missing_variants = vec![];
             if inlined_arms.is_empty() {
                 let scrutinee_is_uninhabited = if self.tcx.features().exhaustive_patterns {
                     self.tcx.is_ty_uninhabited_from(module, pat_ty)
                 } else {
                     match pat_ty.sty {
                         ty::Never => true,
-                        ty::Adt(def, _) => def.variants.is_empty(),
+                        ty::Adt(def, _) => {
+                            def_span = self.tcx.hir().span_if_local(def.did);
+                            if def.variants.len() < 4 && !def.variants.is_empty() {
+                                // keep around to point at the definition of non-covered variants
+                                missing_variants = def.variants.iter()
+                                    .map(|variant| variant.ident.span)
+                                    .collect();
+                            }
+                            def.variants.is_empty()
+                        },
                         _ => false
                     }
                 };
                 if !scrutinee_is_uninhabited {
                     // We know the type is inhabited, so this must be wrong
-                    let mut err = create_e0004(self.tcx.sess, scrut.span,
-                                               format!("non-exhaustive patterns: type `{}` \
-                                                        is non-empty",
-                                                       pat_ty));
-                    span_help!(&mut err, scrut.span,
-                               "ensure that all possible cases are being handled, \
-                                possibly by adding wildcards or more match arms");
+                    let mut err = create_e0004(self.tcx.sess, scrut.span, format!(
+                        "non-exhaustive patterns: type `{}` is non-empty",
+                        pat_ty,
+                    ));
+                    err.help("ensure that all possible cases are being handled, \
+                              possibly by adding wildcards or more match arms");
+                    if let Some(sp) = def_span {
+                        err.span_label(sp, format!("`{}` defined here", pat_ty));
+                    }
+                    // point at the definition of non-covered enum variants
+                    for variant in &missing_variants {
+                        err.span_label(*variant, "variant not covered");
+                    }
                     err.emit();
                 }
                 // If the type *is* uninhabited, it's vacuously exhaustive
@@ -264,7 +281,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
             };
 
             let pattern_string = witness[0].single_pattern().to_string();
-            let mut diag = struct_span_err!(
+            let mut err = struct_span_err!(
                 self.tcx.sess, pat.span, E0005,
                 "refutable pattern in {}: `{}` not covered",
                 origin, pattern_string
@@ -277,8 +294,13 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
                 }
                 _ => format!("pattern `{}` not covered", pattern_string),
             };
-            diag.span_label(pat.span, label_msg);
-            diag.emit();
+            err.span_label(pat.span, label_msg);
+            if let ty::Adt(def, _) = pattern_ty.sty {
+                if let Some(sp) = self.tcx.hir().span_if_local(def.did){
+                    err.span_label(sp, format!("`{}` defined here", pattern_ty));
+                }
+            }
+            err.emit();
         });
     }
 }
@@ -332,10 +354,11 @@ fn pat_is_catchall(pat: &Pat) -> bool {
 }
 
 // Check for unreachable patterns
-fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
-                        arms: &[(Vec<(&'a Pattern<'tcx>, &hir::Pat)>, Option<&hir::Expr>)],
-                        source: hir::MatchSource)
-{
+fn check_arms<'a, 'tcx>(
+    cx: &mut MatchCheckCtxt<'a, 'tcx>,
+    arms: &[(Vec<(&'a Pattern<'tcx>, &hir::Pat)>, Option<&hir::Expr>)],
+    source: hir::MatchSource,
+) {
     let mut seen = Matrix::empty();
     let mut catchall = None;
     for (arm_index, &(ref pats, guard)) in arms.iter().enumerate() {
@@ -411,10 +434,12 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
     }
 }
 
-fn check_exhaustive<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
-                              scrut_ty: Ty<'tcx>,
-                              sp: Span,
-                              matrix: &Matrix<'p, 'tcx>) {
+fn check_exhaustive<'p, 'a: 'p, 'tcx: 'a>(
+    cx: &mut MatchCheckCtxt<'a, 'tcx>,
+    scrut_ty: Ty<'tcx>,
+    sp: Span,
+    matrix: &Matrix<'p, 'tcx>,
+) {
     let wild_pattern = Pattern {
         ty: scrut_ty,
         span: DUMMY_SP,
@@ -448,11 +473,26 @@ fn check_exhaustive<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                 1 => format!("pattern {} not covered", joined_patterns),
                 _ => format!("patterns {} not covered", joined_patterns),
             };
-            create_e0004(cx.tcx.sess, sp,
-                            format!("non-exhaustive patterns: {} not covered",
-                                    joined_patterns))
-                .span_label(sp, label_text)
-                .emit();
+            let mut err = create_e0004(cx.tcx.sess, sp, format!(
+                "non-exhaustive patterns: {} not covered",
+                joined_patterns,
+            ));
+            err.span_label(sp, label_text);
+            // point at the definition of non-covered enum variants
+            if let ty::Adt(def, _) = scrut_ty.sty {
+                if let Some(sp) = cx.tcx.hir().span_if_local(def.did){
+                    err.span_label(sp, format!("`{}` defined here", scrut_ty));
+                }
+            }
+            let patterns = witnesses.iter().map(|p| (**p).clone()).collect::<Vec<Pattern>>();
+            if patterns.len() < 4 {
+                for sp in maybe_point_at_variant(cx, &scrut_ty.sty, patterns.as_slice()) {
+                    err.span_label(sp, "not covered");
+                }
+            }
+            err.help("ensure that all possible cases are being handled, \
+                      possibly by adding wildcards or more match arms");
+            err.emit();
         }
         NotUseful => {
             // This is good, wildcard pattern isn't reachable
@@ -461,10 +501,48 @@ fn check_exhaustive<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
     }
 }
 
+fn maybe_point_at_variant(
+    cx: &mut MatchCheckCtxt<'a, 'tcx>,
+    sty: &TyKind<'tcx>,
+    patterns: &[Pattern],
+) -> Vec<Span> {
+    let mut covered = vec![];
+    if let ty::Adt(def, _) = sty {
+        // Don't point at the variants if they are too many to avoid visual clutter
+        for pattern in patterns {
+            let pk: &PatternKind = &pattern.kind;
+            if let PatternKind::Variant { adt_def, variant_index, subpatterns, .. } = pk {
+                if adt_def.did == def.did {
+                    let sp = def.variants[*variant_index].ident.span;
+                    if covered.contains(&sp) {
+                        continue;
+                    }
+                    covered.push(sp);
+                    let subpatterns = subpatterns.iter()
+                        .map(|field_pattern| field_pattern.pattern.clone())
+                        .collect::<Vec<_>>();
+                    covered.extend(
+                        maybe_point_at_variant(cx, sty, subpatterns.as_slice()),
+                    );
+                }
+            }
+            if let PatternKind::Leaf{ subpatterns } = pk {
+                let subpatterns = subpatterns.iter()
+                    .map(|field_pattern| field_pattern.pattern.clone())
+                    .collect::<Vec<_>>();
+                covered.extend(maybe_point_at_variant(cx, sty, subpatterns.as_slice()));
+            }
+        }
+    }
+    covered
+}
+
 // Legality of move bindings checking
-fn check_legality_of_move_bindings(cx: &MatchVisitor<'_, '_>,
-                                   has_guard: bool,
-                                   pats: &[P<Pat>]) {
+fn check_legality_of_move_bindings(
+    cx: &MatchVisitor<'_, '_>,
+    has_guard: bool,
+    pats: &[P<Pat>],
+) {
     let mut by_ref_span = None;
     for pat in pats {
         pat.each_binding(|_, hir_id, span, _path| {
diff --git a/src/test/ui/always-inhabited-union-ref.stderr b/src/test/ui/always-inhabited-union-ref.stderr
index 212f5d7c525..792ab6f59a4 100644
--- a/src/test/ui/always-inhabited-union-ref.stderr
+++ b/src/test/ui/always-inhabited-union-ref.stderr
@@ -4,11 +4,7 @@ error[E0004]: non-exhaustive patterns: type `&'static !` is non-empty
 LL |     match uninhab_ref() {
    |           ^^^^^^^^^^^^^
    |
-help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-  --> $DIR/always-inhabited-union-ref.rs:23:11
-   |
-LL |     match uninhab_ref() {
-   |           ^^^^^^^^^^^^^
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: type `Foo` is non-empty
   --> $DIR/always-inhabited-union-ref.rs:27:11
@@ -16,11 +12,7 @@ error[E0004]: non-exhaustive patterns: type `Foo` is non-empty
 LL |     match uninhab_union() {
    |           ^^^^^^^^^^^^^^^
    |
-help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-  --> $DIR/always-inhabited-union-ref.rs:27:11
-   |
-LL |     match uninhab_union() {
-   |           ^^^^^^^^^^^^^^^
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/check_match/issue-35609.stderr b/src/test/ui/check_match/issue-35609.stderr
index 7a517e856cb..54e5c988f8c 100644
--- a/src/test/ui/check_match/issue-35609.stderr
+++ b/src/test/ui/check_match/issue-35609.stderr
@@ -3,48 +3,70 @@ error[E0004]: non-exhaustive patterns: `(B, _)`, `(C, _)`, `(D, _)` and 2 more n
    |
 LL |     match (A, ()) { //~ ERROR non-exhaustive
    |           ^^^^^^^ patterns `(B, _)`, `(C, _)`, `(D, _)` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `(_, B)`, `(_, C)`, `(_, D)` and 2 more not covered
   --> $DIR/issue-35609.rs:14:11
    |
 LL |     match (A, A) { //~ ERROR non-exhaustive
    |           ^^^^^^ patterns `(_, B)`, `(_, C)`, `(_, D)` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
   --> $DIR/issue-35609.rs:18:11
    |
 LL |     match ((A, ()), ()) { //~ ERROR non-exhaustive
    |           ^^^^^^^^^^^^^ patterns `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
   --> $DIR/issue-35609.rs:22:11
    |
 LL |     match ((A, ()), A) { //~ ERROR non-exhaustive
    |           ^^^^^^^^^^^^ patterns `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
   --> $DIR/issue-35609.rs:26:11
    |
 LL |     match ((A, ()), ()) { //~ ERROR non-exhaustive
    |           ^^^^^^^^^^^^^ patterns `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `S(B, _)`, `S(C, _)`, `S(D, _)` and 2 more not covered
   --> $DIR/issue-35609.rs:31:11
    |
+LL | struct S(Enum, ());
+   | ------------------- `S` defined here
+...
 LL |     match S(A, ()) { //~ ERROR non-exhaustive
    |           ^^^^^^^^ patterns `S(B, _)`, `S(C, _)`, `S(D, _)` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `Sd { x: B, .. }`, `Sd { x: C, .. }`, `Sd { x: D, .. }` and 2 more not covered
   --> $DIR/issue-35609.rs:35:11
    |
+LL | struct Sd { x: Enum, y: () }
+   | ---------------------------- `Sd` defined here
+...
 LL |     match (Sd { x: A, y: () }) { //~ ERROR non-exhaustive
    |           ^^^^^^^^^^^^^^^^^^^^ patterns `Sd { x: B, .. }`, `Sd { x: C, .. }`, `Sd { x: D, .. }` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `Some(B)`, `Some(C)`, `Some(D)` and 2 more not covered
   --> $DIR/issue-35609.rs:39:11
    |
 LL |     match Some(A) { //~ ERROR non-exhaustive
    |           ^^^^^^^ patterns `Some(B)`, `Some(C)`, `Some(D)` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/consts/match_ice.stderr b/src/test/ui/consts/match_ice.stderr
index e6e04e2c462..d9840231695 100644
--- a/src/test/ui/consts/match_ice.stderr
+++ b/src/test/ui/consts/match_ice.stderr
@@ -3,6 +3,8 @@ error[E0004]: non-exhaustive patterns: `&S` not covered
    |
 LL |     match C { //~ ERROR non-exhaustive
    |           ^ pattern `&S` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/empty/empty-never-array.stderr b/src/test/ui/empty/empty-never-array.stderr
index e409f14d6ce..f1be4a6edec 100644
--- a/src/test/ui/empty/empty-never-array.stderr
+++ b/src/test/ui/empty/empty-never-array.stderr
@@ -1,8 +1,15 @@
 error[E0005]: refutable pattern in local binding: `T(_, _)` not covered
   --> $DIR/empty-never-array.rs:10:9
    |
-LL |     let Helper::U(u) = Helper::T(t, []);
-   |         ^^^^^^^^^^^^ pattern `T(_, _)` not covered
+LL | / enum Helper<T, U> {
+LL | |     T(T, [!; 0]),
+LL | |     #[allow(dead_code)]
+LL | |     U(U),
+LL | | }
+   | |_- `Helper<T, U>` defined here
+...
+LL |       let Helper::U(u) = Helper::T(t, []);
+   |           ^^^^^^^^^^^^ pattern `T(_, _)` not covered
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0004-2.stderr b/src/test/ui/error-codes/E0004-2.stderr
index 8b262cc6eb7..94e38cf26aa 100644
--- a/src/test/ui/error-codes/E0004-2.stderr
+++ b/src/test/ui/error-codes/E0004-2.stderr
@@ -4,11 +4,7 @@ error[E0004]: non-exhaustive patterns: type `std::option::Option<i32>` is non-em
 LL |     match x { } //~ ERROR E0004
    |           ^
    |
-help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-  --> $DIR/E0004-2.rs:4:11
-   |
-LL |     match x { } //~ ERROR E0004
-   |           ^
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0004.stderr b/src/test/ui/error-codes/E0004.stderr
index a66dd929032..123f4b2f1b7 100644
--- a/src/test/ui/error-codes/E0004.stderr
+++ b/src/test/ui/error-codes/E0004.stderr
@@ -1,8 +1,17 @@
 error[E0004]: non-exhaustive patterns: `HastaLaVistaBaby` not covered
   --> $DIR/E0004.rs:9:11
    |
-LL |     match x { //~ ERROR E0004
-   |           ^ pattern `HastaLaVistaBaby` not covered
+LL | / enum Terminator {
+LL | |     HastaLaVistaBaby,
+   | |     ---------------- not covered
+LL | |     TalkToMyHand,
+LL | | }
+   | |_- `Terminator` defined here
+...
+LL |       match x { //~ ERROR E0004
+   |             ^ pattern `HastaLaVistaBaby` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/exhaustive_integer_patterns.stderr b/src/test/ui/exhaustive_integer_patterns.stderr
index 7b873f7ba42..d9513710d44 100644
--- a/src/test/ui/exhaustive_integer_patterns.stderr
+++ b/src/test/ui/exhaustive_integer_patterns.stderr
@@ -15,12 +15,16 @@ error[E0004]: non-exhaustive patterns: `128u8..=255u8` not covered
    |
 LL |     match x { //~ ERROR non-exhaustive patterns
    |           ^ pattern `128u8..=255u8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `11u8..=19u8`, `31u8..=34u8`, `36u8..=69u8` and 1 more not covered
   --> $DIR/exhaustive_integer_patterns.rs:33:11
    |
 LL |     match x { //~ ERROR non-exhaustive patterns
    |           ^ patterns `11u8..=19u8`, `31u8..=34u8`, `36u8..=69u8` and 1 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: unreachable pattern
   --> $DIR/exhaustive_integer_patterns.rs:44:9
@@ -33,54 +37,72 @@ error[E0004]: non-exhaustive patterns: `-128i8..=-8i8`, `-6i8`, `121i8..=124i8`
    |
 LL |     match x { //~ ERROR non-exhaustive patterns
    |           ^ patterns `-128i8..=-8i8`, `-6i8`, `121i8..=124i8` and 1 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `-128i8` not covered
   --> $DIR/exhaustive_integer_patterns.rs:82:11
    |
 LL |     match 0i8 { //~ ERROR non-exhaustive patterns
    |           ^^^ pattern `-128i8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `0i16` not covered
   --> $DIR/exhaustive_integer_patterns.rs:90:11
    |
 LL |     match 0i16 { //~ ERROR non-exhaustive patterns
    |           ^^^^ pattern `0i16` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `128u8..=255u8` not covered
   --> $DIR/exhaustive_integer_patterns.rs:108:11
    |
 LL |     match 0u8 { //~ ERROR non-exhaustive patterns
    |           ^^^ pattern `128u8..=255u8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `(0u8, Some(_))` and `(2u8..=255u8, Some(_))` not covered
   --> $DIR/exhaustive_integer_patterns.rs:120:11
    |
 LL |     match (0u8, Some(())) { //~ ERROR non-exhaustive patterns
    |           ^^^^^^^^^^^^^^^ patterns `(0u8, Some(_))` and `(2u8..=255u8, Some(_))` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `(126u8..=127u8, false)` not covered
   --> $DIR/exhaustive_integer_patterns.rs:125:11
    |
 LL |     match (0u8, true) { //~ ERROR non-exhaustive patterns
    |           ^^^^^^^^^^^ pattern `(126u8..=127u8, false)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211455u128` not covered
   --> $DIR/exhaustive_integer_patterns.rs:145:11
    |
 LL |     match 0u128 { //~ ERROR non-exhaustive patterns
    |           ^^^^^ pattern `340282366920938463463374607431768211455u128` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `5u128..=340282366920938463463374607431768211455u128` not covered
   --> $DIR/exhaustive_integer_patterns.rs:149:11
    |
 LL |     match 0u128 { //~ ERROR non-exhaustive patterns
    |           ^^^^^ pattern `5u128..=340282366920938463463374607431768211455u128` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `0u128..=3u128` not covered
   --> $DIR/exhaustive_integer_patterns.rs:153:11
    |
 LL |     match 0u128 { //~ ERROR non-exhaustive patterns
    |           ^^^^^ pattern `0u128..=3u128` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to 13 previous errors
 
diff --git a/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr b/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr
index 5806f6f0391..fd1e5392e69 100644
--- a/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr
+++ b/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr
@@ -3,12 +3,16 @@ error[E0004]: non-exhaustive patterns: `_` not covered
    |
 LL |     match 0usize { //~ERROR non-exhaustive patterns: `_` not covered
    |           ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `_` not covered
   --> $DIR/feature-gate-precise_pointer_size_matching.rs:10:11
    |
 LL |     match 0isize { //~ERROR non-exhaustive patterns: `_` not covered
    |           ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-15129.stderr b/src/test/ui/issues/issue-15129.stderr
index 7ee36908520..b93fa14db03 100644
--- a/src/test/ui/issues/issue-15129.stderr
+++ b/src/test/ui/issues/issue-15129.stderr
@@ -3,6 +3,8 @@ error[E0004]: non-exhaustive patterns: `(T1(()), V2(_))` not covered
    |
 LL |     match (T::T1(()), V::V2(true)) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `(T1(()), V2(_))` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-2111.stderr b/src/test/ui/issues/issue-2111.stderr
index 348ad153c80..90fdb48ea62 100644
--- a/src/test/ui/issues/issue-2111.stderr
+++ b/src/test/ui/issues/issue-2111.stderr
@@ -3,6 +3,8 @@ error[E0004]: non-exhaustive patterns: `(None, None)` not covered
    |
 LL |   match (a,b) {
    |         ^^^^^ pattern `(None, None)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-30240.stderr b/src/test/ui/issues/issue-30240.stderr
index 973c59c5852..bc538abf3bd 100644
--- a/src/test/ui/issues/issue-30240.stderr
+++ b/src/test/ui/issues/issue-30240.stderr
@@ -3,12 +3,16 @@ error[E0004]: non-exhaustive patterns: `&_` not covered
    |
 LL |     match "world" { //~ ERROR non-exhaustive patterns: `&_`
    |           ^^^^^^^ pattern `&_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&_` not covered
   --> $DIR/issue-30240.rs:6:11
    |
 LL |     match "world" { //~ ERROR non-exhaustive patterns: `&_`
    |           ^^^^^^^ pattern `&_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-3096-1.stderr b/src/test/ui/issues/issue-3096-1.stderr
index 7ced0d36805..fee58474031 100644
--- a/src/test/ui/issues/issue-3096-1.stderr
+++ b/src/test/ui/issues/issue-3096-1.stderr
@@ -4,11 +4,7 @@ error[E0004]: non-exhaustive patterns: type `()` is non-empty
 LL |     match () { } //~ ERROR non-exhaustive
    |           ^^
    |
-help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-  --> $DIR/issue-3096-1.rs:2:11
-   |
-LL |     match () { } //~ ERROR non-exhaustive
-   |           ^^
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-3096-2.stderr b/src/test/ui/issues/issue-3096-2.stderr
index df876794489..93119d37744 100644
--- a/src/test/ui/issues/issue-3096-2.stderr
+++ b/src/test/ui/issues/issue-3096-2.stderr
@@ -4,11 +4,7 @@ error[E0004]: non-exhaustive patterns: type `*const Bottom` is non-empty
 LL |     match x { } //~ ERROR non-exhaustive patterns
    |           ^
    |
-help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-  --> $DIR/issue-3096-2.rs:5:11
-   |
-LL |     match x { } //~ ERROR non-exhaustive patterns
-   |           ^
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-31561.stderr b/src/test/ui/issues/issue-31561.stderr
index c95fc36cea6..246137aeee0 100644
--- a/src/test/ui/issues/issue-31561.stderr
+++ b/src/test/ui/issues/issue-31561.stderr
@@ -1,8 +1,15 @@
 error[E0005]: refutable pattern in local binding: `Bar` not covered
   --> $DIR/issue-31561.rs:8:9
    |
-LL |     let Thing::Foo(y) = Thing::Foo(1);
-   |         ^^^^^^^^^^^^^ pattern `Bar` not covered
+LL | / enum Thing {
+LL | |     Foo(u8),
+LL | |     Bar,
+LL | |     Baz
+LL | | }
+   | |_- `Thing` defined here
+...
+LL |       let Thing::Foo(y) = Thing::Foo(1);
+   |           ^^^^^^^^^^^^^ pattern `Bar` not covered
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-3601.stderr b/src/test/ui/issues/issue-3601.stderr
index 0b5242ee528..85b53443434 100644
--- a/src/test/ui/issues/issue-3601.stderr
+++ b/src/test/ui/issues/issue-3601.stderr
@@ -3,6 +3,8 @@ error[E0004]: non-exhaustive patterns: `_` not covered
    |
 LL |         box NodeKind::Element(ed) => match ed.kind { //~ ERROR non-exhaustive patterns
    |                                            ^^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-39362.stderr b/src/test/ui/issues/issue-39362.stderr
index 06385127e94..55cd14a5c1e 100644
--- a/src/test/ui/issues/issue-39362.stderr
+++ b/src/test/ui/issues/issue-39362.stderr
@@ -1,8 +1,15 @@
 error[E0004]: non-exhaustive patterns: `Bar { bar: C, .. }`, `Bar { bar: D, .. }`, `Bar { bar: E, .. }` and 1 more not covered
   --> $DIR/issue-39362.rs:10:11
    |
-LL |     match f {
-   |           ^ patterns `Bar { bar: C, .. }`, `Bar { bar: D, .. }`, `Bar { bar: E, .. }` and 1 more not covered
+LL | / enum Foo {
+LL | |     Bar { bar: Bar, id: usize }
+LL | | }
+   | |_- `Foo` defined here
+...
+LL |       match f {
+   |             ^ patterns `Bar { bar: C, .. }`, `Bar { bar: D, .. }`, `Bar { bar: E, .. }` and 1 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-4321.stderr b/src/test/ui/issues/issue-4321.stderr
index 7817fdcbce9..731e63fbb2b 100644
--- a/src/test/ui/issues/issue-4321.stderr
+++ b/src/test/ui/issues/issue-4321.stderr
@@ -3,6 +3,8 @@ error[E0004]: non-exhaustive patterns: `(true, false)` not covered
    |
 LL |     println!("foo {:}", match tup { //~ ERROR non-exhaustive patterns: `(true, false)` not covered
    |                               ^^^ pattern `(true, false)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/match/match-argm-statics-2.stderr b/src/test/ui/match/match-argm-statics-2.stderr
index 3e6f22ab875..8c54e030823 100644
--- a/src/test/ui/match/match-argm-statics-2.stderr
+++ b/src/test/ui/match/match-argm-statics-2.stderr
@@ -3,18 +3,30 @@ error[E0004]: non-exhaustive patterns: `(true, false)` not covered
    |
 LL |     match (true, false) {
    |           ^^^^^^^^^^^^^ pattern `(true, false)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `Some(Some(West))` not covered
   --> $DIR/match-argm-statics-2.rs:29:11
    |
 LL |     match Some(Some(North)) {
    |           ^^^^^^^^^^^^^^^^^ pattern `Some(Some(West))` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `Foo { bar: Some(North), baz: NewBool(true) }` not covered
   --> $DIR/match-argm-statics-2.rs:48:11
    |
-LL |     match (Foo { bar: Some(North), baz: NewBool(true) }) {
-   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { bar: Some(North), baz: NewBool(true) }` not covered
+LL | / struct Foo {
+LL | |     bar: Option<Direction>,
+LL | |     baz: NewBool
+LL | | }
+   | |_- `Foo` defined here
+...
+LL |       match (Foo { bar: Some(North), baz: NewBool(true) }) {
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { bar: Some(North), baz: NewBool(true) }` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/match/match-byte-array-patterns-2.stderr b/src/test/ui/match/match-byte-array-patterns-2.stderr
index 4030cd39448..83dbecfcac6 100644
--- a/src/test/ui/match/match-byte-array-patterns-2.stderr
+++ b/src/test/ui/match/match-byte-array-patterns-2.stderr
@@ -3,12 +3,16 @@ error[E0004]: non-exhaustive patterns: `&[_, _, _, _]` not covered
    |
 LL |     match buf { //~ ERROR non-exhaustive
    |           ^^^ pattern `&[_, _, _, _]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 3 more not covered
   --> $DIR/match-byte-array-patterns-2.rs:10:11
    |
 LL |     match buf { //~ ERROR non-exhaustive
    |           ^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 3 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/match/match-non-exhaustive.stderr b/src/test/ui/match/match-non-exhaustive.stderr
index ab5ab18c328..9921e4f63b6 100644
--- a/src/test/ui/match/match-non-exhaustive.stderr
+++ b/src/test/ui/match/match-non-exhaustive.stderr
@@ -3,12 +3,16 @@ error[E0004]: non-exhaustive patterns: `-2147483648i32..=0i32` and `2i32..=21474
    |
 LL |     match 0 { 1 => () } //~ ERROR non-exhaustive patterns
    |           ^ patterns `-2147483648i32..=0i32` and `2i32..=2147483647i32` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `_` not covered
   --> $DIR/match-non-exhaustive.rs:3:11
    |
 LL |     match 0 { 0 if false => () } //~ ERROR non-exhaustive patterns
    |           ^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/match/match-privately-empty.stderr b/src/test/ui/match/match-privately-empty.stderr
index 23ca64e50af..f79d180a1b8 100644
--- a/src/test/ui/match/match-privately-empty.stderr
+++ b/src/test/ui/match/match-privately-empty.stderr
@@ -3,6 +3,8 @@ error[E0004]: non-exhaustive patterns: `Some(Private { misc: true, .. })` not co
    |
 LL |     match private::DATA {
    |           ^^^^^^^^^^^^^ pattern `Some(Private { misc: true, .. })` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/match/match-slice-patterns.stderr b/src/test/ui/match/match-slice-patterns.stderr
index 2b817498aba..24769db34c9 100644
--- a/src/test/ui/match/match-slice-patterns.stderr
+++ b/src/test/ui/match/match-slice-patterns.stderr
@@ -3,6 +3,8 @@ error[E0004]: non-exhaustive patterns: `&[_, Some(_), None, _]` not covered
    |
 LL |     match list {
    |           ^^^^ pattern `&[_, Some(_), None, _]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/missing/missing-items/issue-40221.stderr b/src/test/ui/missing/missing-items/issue-40221.stderr
index 437fb7bbc31..9e4ce7c81b7 100644
--- a/src/test/ui/missing/missing-items/issue-40221.stderr
+++ b/src/test/ui/missing/missing-items/issue-40221.stderr
@@ -1,8 +1,16 @@
 error[E0004]: non-exhaustive patterns: `C(QA)` not covered
   --> $DIR/issue-40221.rs:11:11
    |
-LL |     match proto { //~ ERROR non-exhaustive patterns
-   |           ^^^^^ pattern `C(QA)` not covered
+LL | / enum P {
+LL | |     C(PC),
+   | |     - not covered
+LL | | }
+   | |_- `P` defined here
+...
+LL |       match proto { //~ ERROR non-exhaustive patterns
+   |             ^^^^^ pattern `C(QA)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/non-exhaustive/non-exhaustive-float-range-match.stderr b/src/test/ui/non-exhaustive/non-exhaustive-float-range-match.stderr
index 2e285afb380..03215f72ebc 100644
--- a/src/test/ui/non-exhaustive/non-exhaustive-float-range-match.stderr
+++ b/src/test/ui/non-exhaustive/non-exhaustive-float-range-match.stderr
@@ -3,6 +3,8 @@ error[E0004]: non-exhaustive patterns: `_` not covered
    |
 LL |     match 0.0 { //~ ERROR non-exhaustive patterns
    |           ^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/non-exhaustive/non-exhaustive-match-nested.stderr b/src/test/ui/non-exhaustive/non-exhaustive-match-nested.stderr
index b2551c8dcf2..d5beac4b716 100644
--- a/src/test/ui/non-exhaustive/non-exhaustive-match-nested.stderr
+++ b/src/test/ui/non-exhaustive/non-exhaustive-match-nested.stderr
@@ -3,12 +3,22 @@ error[E0004]: non-exhaustive patterns: `(Some(&[]), Err(_))` not covered
    |
 LL |     match (l1, l2) { //~ ERROR non-exhaustive patterns: `(Some(&[]), Err(_))` not covered
    |           ^^^^^^^^ pattern `(Some(&[]), Err(_))` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `A(C)` not covered
   --> $DIR/non-exhaustive-match-nested.rs:17:11
    |
+LL | enum T { A(U), B }
+   | ------------------
+   | |        |
+   | |        not covered
+   | `T` defined here
+...
 LL |     match x { //~ ERROR non-exhaustive patterns: `A(C)` not covered
    |           ^ pattern `A(C)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/non-exhaustive/non-exhaustive-match.stderr b/src/test/ui/non-exhaustive/non-exhaustive-match.stderr
index 8d2a73b2c6d..112e18432b4 100644
--- a/src/test/ui/non-exhaustive/non-exhaustive-match.stderr
+++ b/src/test/ui/non-exhaustive/non-exhaustive-match.stderr
@@ -1,50 +1,78 @@
 error[E0004]: non-exhaustive patterns: `A` not covered
   --> $DIR/non-exhaustive-match.rs:8:11
    |
+LL | enum T { A, B }
+   | ---------------
+   | |        |
+   | |        not covered
+   | `T` defined here
+...
 LL |     match x { T::B => { } } //~ ERROR non-exhaustive patterns: `A` not covered
    |           ^ pattern `A` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `false` not covered
   --> $DIR/non-exhaustive-match.rs:9:11
    |
 LL |     match true { //~ ERROR non-exhaustive patterns: `false` not covered
    |           ^^^^ pattern `false` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `Some(_)` not covered
   --> $DIR/non-exhaustive-match.rs:12:11
    |
 LL |     match Some(10) { //~ ERROR non-exhaustive patterns: `Some(_)` not covered
    |           ^^^^^^^^ pattern `Some(_)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `(_, _, -2147483648i32..=3i32)` and `(_, _, 5i32..=2147483647i32)` not covered
   --> $DIR/non-exhaustive-match.rs:15:11
    |
 LL |     match (2, 3, 4) { //~ ERROR non-exhaustive patterns: `(_, _, -2147483648i32..=3i32)`
    |           ^^^^^^^^^ patterns `(_, _, -2147483648i32..=3i32)` and `(_, _, 5i32..=2147483647i32)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `(A, A)` not covered
   --> $DIR/non-exhaustive-match.rs:19:11
    |
 LL |     match (T::A, T::A) { //~ ERROR non-exhaustive patterns: `(A, A)` not covered
    |           ^^^^^^^^^^^^ pattern `(A, A)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `B` not covered
   --> $DIR/non-exhaustive-match.rs:23:11
    |
+LL | enum T { A, B }
+   | ---------------
+   | |           |
+   | |           not covered
+   | `T` defined here
+...
 LL |     match T::A { //~ ERROR non-exhaustive patterns: `B` not covered
    |           ^^^^ pattern `B` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `[]` not covered
   --> $DIR/non-exhaustive-match.rs:34:11
    |
 LL |     match *vec { //~ ERROR non-exhaustive patterns: `[]` not covered
    |           ^^^^ pattern `[]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `[_, _, _, _]` not covered
   --> $DIR/non-exhaustive-match.rs:47:11
    |
 LL |     match *vec { //~ ERROR non-exhaustive patterns: `[_, _, _, _]` not covered
    |           ^^^^ pattern `[_, _, _, _]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/non-exhaustive/non-exhaustive-pattern-witness.stderr b/src/test/ui/non-exhaustive/non-exhaustive-pattern-witness.stderr
index d3a06e7b4b6..a0b497dd4c0 100644
--- a/src/test/ui/non-exhaustive/non-exhaustive-pattern-witness.stderr
+++ b/src/test/ui/non-exhaustive/non-exhaustive-pattern-witness.stderr
@@ -1,44 +1,94 @@
 error[E0004]: non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered
   --> $DIR/non-exhaustive-pattern-witness.rs:9:11
    |
-LL |     match (Foo { first: true, second: None }) {
-   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { first: false, second: Some([_, _, _, _]) }` not covered
+LL | / struct Foo {
+LL | |     first: bool,
+LL | |     second: Option<[usize; 4]>
+LL | | }
+   | |_- `Foo` defined here
+...
+LL |       match (Foo { first: true, second: None }) {
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { first: false, second: Some([_, _, _, _]) }` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `Red` not covered
   --> $DIR/non-exhaustive-pattern-witness.rs:25:11
    |
-LL |     match Color::Red {
-   |           ^^^^^^^^^^ pattern `Red` not covered
+LL | / enum Color {
+LL | |     Red,
+   | |     --- not covered
+LL | |     Green,
+LL | |     CustomRGBA { a: bool, r: u8, g: u8, b: u8 }
+LL | | }
+   | |_- `Color` defined here
+...
+LL |       match Color::Red {
+   |             ^^^^^^^^^^ pattern `Red` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `East`, `South` and `West` not covered
   --> $DIR/non-exhaustive-pattern-witness.rs:37:11
    |
-LL |     match Direction::North {
-   |           ^^^^^^^^^^^^^^^^ patterns `East`, `South` and `West` not covered
+LL | / enum Direction {
+LL | |     North, East, South, West
+   | |            ----  -----  ---- not covered
+   | |            |     |
+   | |            |     not covered
+   | |            not covered
+LL | | }
+   | |_- `Direction` defined here
+...
+LL |       match Direction::North {
+   |             ^^^^^^^^^^^^^^^^ patterns `East`, `South` and `West` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `Second`, `Third`, `Fourth` and 8 more not covered
   --> $DIR/non-exhaustive-pattern-witness.rs:48:11
    |
-LL |     match ExcessiveEnum::First {
-   |           ^^^^^^^^^^^^^^^^^^^^ patterns `Second`, `Third`, `Fourth` and 8 more not covered
+LL | / enum ExcessiveEnum {
+LL | |     First, Second, Third, Fourth, Fifth, Sixth, Seventh, Eighth, Ninth, Tenth, Eleventh, Twelfth
+LL | | }
+   | |_- `ExcessiveEnum` defined here
+...
+LL |       match ExcessiveEnum::First {
+   |             ^^^^^^^^^^^^^^^^^^^^ patterns `Second`, `Third`, `Fourth` and 8 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `CustomRGBA { a: true, .. }` not covered
   --> $DIR/non-exhaustive-pattern-witness.rs:56:11
    |
-LL |     match Color::Red {
-   |           ^^^^^^^^^^ pattern `CustomRGBA { a: true, .. }` not covered
+LL | / enum Color {
+LL | |     Red,
+LL | |     Green,
+LL | |     CustomRGBA { a: bool, r: u8, g: u8, b: u8 }
+   | |     ---------- not covered
+LL | | }
+   | |_- `Color` defined here
+...
+LL |       match Color::Red {
+   |             ^^^^^^^^^^ pattern `CustomRGBA { a: true, .. }` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `[Second(true), Second(false)]` not covered
   --> $DIR/non-exhaustive-pattern-witness.rs:72:11
    |
 LL |     match *x {
    |           ^^ pattern `[Second(true), Second(false)]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `((), false)` not covered
   --> $DIR/non-exhaustive-pattern-witness.rs:85:11
    |
 LL |     match ((), false) {
    |           ^^^^^^^^^^^ pattern `((), false)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/precise_pointer_size_matching.stderr b/src/test/ui/precise_pointer_size_matching.stderr
index 4acbec6c7ff..a8906a43003 100644
--- a/src/test/ui/precise_pointer_size_matching.stderr
+++ b/src/test/ui/precise_pointer_size_matching.stderr
@@ -3,12 +3,16 @@ error[E0004]: non-exhaustive patterns: `$ISIZE_MIN..=-6isize` and `21isize..=$IS
    |
 LL |     match 0isize { //~ ERROR non-exhaustive patterns
    |           ^^^^^^ patterns `$ISIZE_MIN..=-6isize` and `21isize..=$ISIZE_MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `0usize` and `21usize..=$USIZE_MAX` not covered
   --> $DIR/precise_pointer_size_matching.rs:29:11
    |
 LL |     match 0usize { //~ ERROR non-exhaustive patterns
    |           ^^^^^^ patterns `0usize` and `21usize..=$USIZE_MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/rfc-2005-default-binding-mode/slice.stderr b/src/test/ui/rfc-2005-default-binding-mode/slice.stderr
index 1dfad0d3189..e24c8f15559 100644
--- a/src/test/ui/rfc-2005-default-binding-mode/slice.stderr
+++ b/src/test/ui/rfc-2005-default-binding-mode/slice.stderr
@@ -3,6 +3,8 @@ error[E0004]: non-exhaustive patterns: `&[]` not covered
    |
 LL |     match sl { //~ ERROR non-exhaustive patterns
    |           ^^ pattern `&[]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum.stderr b/src/test/ui/rfc-2008-non-exhaustive/enum.stderr
index acce9779067..b5c1a4ebba4 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/enum.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/enum.stderr
@@ -3,6 +3,8 @@ error[E0004]: non-exhaustive patterns: `_` not covered
    |
 LL |     match enum_unit {
    |           ^^^^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/structs/struct-like-enum-nonexhaustive.stderr b/src/test/ui/structs/struct-like-enum-nonexhaustive.stderr
index d651ea0b4e2..0aa85eb7253 100644
--- a/src/test/ui/structs/struct-like-enum-nonexhaustive.stderr
+++ b/src/test/ui/structs/struct-like-enum-nonexhaustive.stderr
@@ -1,8 +1,17 @@
 error[E0004]: non-exhaustive patterns: `B { x: Some(_) }` not covered
   --> $DIR/struct-like-enum-nonexhaustive.rs:8:11
    |
-LL |     match x {   //~ ERROR non-exhaustive patterns
-   |           ^ pattern `B { x: Some(_) }` not covered
+LL | / enum A {
+LL | |     B { x: Option<isize> },
+   | |     - not covered
+LL | |     C
+LL | | }
+   | |_- `A` defined here
+...
+LL |       match x {   //~ ERROR non-exhaustive patterns
+   |             ^ pattern `B { x: Some(_) }` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/tuple/tuple-struct-nonexhaustive.stderr b/src/test/ui/tuple/tuple-struct-nonexhaustive.stderr
index 8d627fc2a8d..58d0862be6d 100644
--- a/src/test/ui/tuple/tuple-struct-nonexhaustive.stderr
+++ b/src/test/ui/tuple/tuple-struct-nonexhaustive.stderr
@@ -1,8 +1,13 @@
 error[E0004]: non-exhaustive patterns: `Foo(_, _)` not covered
   --> $DIR/tuple-struct-nonexhaustive.rs:5:11
    |
+LL | struct Foo(isize, isize);
+   | ------------------------- `Foo` defined here
+...
 LL |     match x {   //~ ERROR non-exhaustive
    |           ^ pattern `Foo(_, _)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr
index 63819bf949b..2424252af2a 100644
--- a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr
+++ b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr
@@ -1,8 +1,16 @@
 error[E0005]: refutable pattern in local binding: `A(_)` not covered
   --> $DIR/uninhabited-irrefutable.rs:27:9
    |
-LL |     let Foo::D(_y) = x; //~ ERROR refutable pattern in local binding: `A(_)` not covered
-   |         ^^^^^^^^^^ pattern `A(_)` not covered
+LL | / enum Foo {
+LL | |     A(foo::SecretlyEmpty),
+LL | |     B(foo::NotSoSecretlyEmpty),
+LL | |     C(NotSoSecretlyEmpty),
+LL | |     D(u32),
+LL | | }
+   | |_- `Foo` defined here
+...
+LL |       let Foo::D(_y) = x; //~ ERROR refutable pattern in local binding: `A(_)` not covered
+   |           ^^^^^^^^^^ pattern `A(_)` not covered
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
index b88dcc9aea4..fec95ca1494 100644
--- a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
+++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
@@ -3,6 +3,8 @@ error[E0004]: non-exhaustive patterns: `Err(_)` not covered
    |
 LL |     let _ = match x {   //~ ERROR non-exhaustive
    |                   ^ pattern `Err(_)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: type `&Void` is non-empty
   --> $DIR/uninhabited-matches-feature-gated.rs:10:19
@@ -10,11 +12,7 @@ error[E0004]: non-exhaustive patterns: type `&Void` is non-empty
 LL |     let _ = match x {}; //~ ERROR non-exhaustive
    |                   ^
    |
-help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-  --> $DIR/uninhabited-matches-feature-gated.rs:10:19
-   |
-LL |     let _ = match x {}; //~ ERROR non-exhaustive
-   |                   ^
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: type `(Void,)` is non-empty
   --> $DIR/uninhabited-matches-feature-gated.rs:13:19
@@ -22,11 +20,7 @@ error[E0004]: non-exhaustive patterns: type `(Void,)` is non-empty
 LL |     let _ = match x {}; //~ ERROR non-exhaustive
    |                   ^
    |
-help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-  --> $DIR/uninhabited-matches-feature-gated.rs:13:19
-   |
-LL |     let _ = match x {}; //~ ERROR non-exhaustive
-   |                   ^
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: type `[Void; 1]` is non-empty
   --> $DIR/uninhabited-matches-feature-gated.rs:16:19
@@ -34,23 +28,23 @@ error[E0004]: non-exhaustive patterns: type `[Void; 1]` is non-empty
 LL |     let _ = match x {}; //~ ERROR non-exhaustive
    |                   ^
    |
-help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-  --> $DIR/uninhabited-matches-feature-gated.rs:16:19
-   |
-LL |     let _ = match x {}; //~ ERROR non-exhaustive
-   |                   ^
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[_]` not covered
   --> $DIR/uninhabited-matches-feature-gated.rs:19:19
    |
 LL |     let _ = match x {   //~ ERROR non-exhaustive
    |                   ^ pattern `&[_]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `Err(_)` not covered
   --> $DIR/uninhabited-matches-feature-gated.rs:27:19
    |
 LL |     let _ = match x {   //~ ERROR non-exhaustive
    |                   ^ pattern `Err(_)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0005]: refutable pattern in local binding: `Err(_)` not covered
   --> $DIR/uninhabited-matches-feature-gated.rs:32:9