Change:
Sorry about the long title :sweat_smile: Given the following code (): The current output is: Note how the first diagnostic, emitted when matching on a , contains additional information about why this exhaustive match does not pass the exhaustiveness check. Ideally, this information should be to the second diagnostic as well: modify labels: +A-exhaustiveness-checking +A-patterns +D-terse
Hm, even though has a different size on different architectures, should always be exhaustive, right? Then that code would be accepted, but the following would still error: We could have the error for this say "missing pattern: ", which would also work if there's a around it. That said, pretty sure what you describe also happens for enums too, and there we'll want to do what you suggest.
see also
I forgot this issue existed, but yeah this is a lint we want. I explained a bit about how this might be done in , if anyone wants to tackle this feel free to ping me

Discussion:
use rustc_arena::TypedArena; use rustc_ast::Mutability; <ins> use rustc_data_structures::fx::FxHashSet; </ins> use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,

} } <ins> fn collect_non_exhaustive_tys<'p, 'tcx>( pat: &DeconstructedPat<'p, 'tcx>, non_exhaustive_tys: &mut FxHashSet<Ty<'tcx>>, ) { if matches!(pat.ctor(), Constructor::NonExhaustive) { non_exhaustive_tys.insert(pat.ty()); } pat.iter_fields() .for_each(|field_pat| collect_non_exhaustive_tys(field_pat, non_exhaustive_tys)) } </ins> /// Report that a match is not exhaustive. fn non_exhaustive_match<'p, 'tcx>( cx: &MatchCheckCtxt<'p, 'tcx>,

scrut_ty, if is_variant_list_non_exhaustive { ", which is marked as non-exhaustive" } else { "" } )); <del> if (scrut_ty == cx.tcx.types.usize || scrut_ty == cx.tcx.types.isize) && !is_empty_match && witnesses.len() == 1 && matches!(witnesses[0].ctor(), Constructor::NonExhaustive) { err.note(format!( "`{scrut_ty}` does not have a fixed maximum value, so a wildcard `_` is necessary to match  exhaustively", )); if cx.tcx.sess.is_nightly_build() { err.help(format!( "add `#![feature(precise_pointer_size_matching)]` to the crate attributes to  enable precise `{scrut_ty}` matching", )); </del> <ins> if !is_empty_match && witnesses.len() == 1 { let mut non_exhaustive_tys = FxHashSet::default(); collect_non_exhaustive_tys(&witnesses[0], &mut non_exhaustive_tys); for ty in non_exhaustive_tys { if ty == cx.tcx.types.usize || ty == cx.tcx.types.isize { err.note(format!( "`{ty}` does not have a fixed maximum value, so a wildcard `_` is necessary to match  exhaustively", )); if cx.tcx.sess.is_nightly_build() { err.help(format!( "add `#![feature(precise_pointer_size_matching)]` to the crate attributes to  enable precise `{ty}` matching", )); } } </ins> } } if let ty::Ref(_, sub_ty, _) = scrut_ty.kind() { if !sub_ty.is_inhabited_from(cx.tcx, cx.module, cx.param_env) { err.note("references are always considered inhabited");

|        ^^^^^^^^^^^^^^ pattern `(_, _)` not covered | = note: the matched value is of type `(usize, bool)` <ins> = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching </ins> help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL |         match $s { $($t)+ => {}, (_, _) => todo!() }

|        ^^^^^^^^^^^^^^ pattern `(_, _)` not covered | = note: the matched value is of type `(isize, bool)` <ins> = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching </ins> help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL |         match $s { $($t)+ => {}, (_, _) => todo!() }

<ins> struct A<T> { a: T, } struct B<T, U>(T, U); fn main() { match 0 { //~^ ERROR non-exhaustive patterns: `_` not covered [E0004] 0 => (), 1..=usize::MAX => (), } match (0usize, 0usize) { //~^ ERROR non-exhaustive patterns: `(_, _)` not covered [E0004] (0, 0) => (), (1..=usize::MAX, 1..=usize::MAX) => (), } match (0isize, 0usize) { //~^ ERROR non-exhaustive patterns: `(_, _)` not covered [E0004] (isize::MIN..=isize::MAX, 0) => (), (isize::MIN..=isize::MAX, 1..=usize::MAX) => (), } // Should not report note about usize not having fixed max value match Some(1usize) { //~^ ERROR non-exhaustive patterns: `Some(_)` not covered None => {} } match Some(4) { //~^ ERROR non-exhaustive patterns: `Some(_)` not covered Some(0) => (), Some(1..=usize::MAX) => (), None => (), } match Some(Some(Some(0))) { //~^ ERROR non-exhaustive patterns: `Some(Some(Some(_)))` not covered Some(Some(Some(0))) => (), Some(Some(Some(1..=usize::MAX))) => (), Some(Some(None)) => (), Some(None) => (), None => (), } match (A { a: 0usize }) { //~^ ERROR non-exhaustive patterns: `A { .. }` not covered [E0004] A { a: 0 } => (), A { a: 1..=usize::MAX } => (), } match B(0isize, 0usize) { //~^ ERROR non-exhaustive patterns: `B(_, _)` not covered [E0004] B(isize::MIN..=isize::MAX, 0) => (), B(isize::MIN..=isize::MAX, 1..=usize::MAX) => (), } // Should report only the note about usize not having fixed max value and not report // report the note about isize match B(0isize, 0usize) { //~^ ERROR non-exhaustive patterns: `B(_, _)` not covered [E0004] B(_, 0) => (), B(_, 1..=usize::MAX) => (), } } </ins>

<ins> error[E0004]: non-exhaustive patterns: `_` not covered --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:8:11 | LL |     match 0 { |           ^ pattern `_` not covered | = note: the matched value is of type `usize` = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~         1..=usize::MAX => (), LL ~         _ => todo!(), | error[E0004]: non-exhaustive patterns: `(_, _)` not covered --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:14:11 | LL |     match (0usize, 0usize) { |           ^^^^^^^^^^^^^^^^ pattern `(_, _)` not covered | = note: the matched value is of type `(usize, usize)` = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~         (1..=usize::MAX, 1..=usize::MAX) => (), LL ~         (_, _) => todo!(), | error[E0004]: non-exhaustive patterns: `(_, _)` not covered --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:20:11 | LL |     match (0isize, 0usize) { |           ^^^^^^^^^^^^^^^^ pattern `(_, _)` not covered | = note: the matched value is of type `(isize, usize)` = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~         (isize::MIN..=isize::MAX, 1..=usize::MAX) => (), LL ~         (_, _) => todo!(), | error[E0004]: non-exhaustive patterns: `Some(_)` not covered --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:27:11 | LL |     match Some(1usize) { |           ^^^^^^^^^^^^ pattern `Some(_)` not covered | note: `Option<usize>` defined here --> $SRC_DIR/core/src/option.rs:LL:COL ::: $SRC_DIR/core/src/option.rs:LL:COL | = note: not covered = note: the matched value is of type `Option<usize>` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~         None => {}, LL +         Some(_) => todo!() | error[E0004]: non-exhaustive patterns: `Some(_)` not covered --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:32:11 | LL |     match Some(4) { |           ^^^^^^^ pattern `Some(_)` not covered | note: `Option<usize>` defined here --> $SRC_DIR/core/src/option.rs:LL:COL ::: $SRC_DIR/core/src/option.rs:LL:COL | = note: not covered = note: the matched value is of type `Option<usize>` = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~         None => (), LL ~         Some(_) => todo!(), | error[E0004]: non-exhaustive patterns: `Some(Some(Some(_)))` not covered --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:39:11 | LL |     match Some(Some(Some(0))) { |           ^^^^^^^^^^^^^^^^^^^ pattern `Some(Some(Some(_)))` not covered | note: `Option<Option<Option<usize>>>` defined here --> $SRC_DIR/core/src/option.rs:LL:COL ::: $SRC_DIR/core/src/option.rs:LL:COL | = note: not covered | = note: not covered | = note: not covered = note: the matched value is of type `Option<Option<Option<usize>>>` = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~         None => (), LL ~         Some(Some(Some(_))) => todo!(), | error[E0004]: non-exhaustive patterns: `A { .. }` not covered --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:48:11 | LL |     match (A { a: 0usize }) { |           ^^^^^^^^^^^^^^^^^ pattern `A { .. }` not covered | note: `A<usize>` defined here --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:1:8 | LL | struct A<T> { |        ^ = note: the matched value is of type `A<usize>` = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~         A { a: 1..=usize::MAX } => (), LL ~         A { .. } => todo!(), | error[E0004]: non-exhaustive patterns: `B(_, _)` not covered --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:54:11 | LL |     match B(0isize, 0usize) { |           ^^^^^^^^^^^^^^^^^ pattern `B(_, _)` not covered | note: `B<isize, usize>` defined here --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:5:8 | LL | struct B<T, U>(T, U); |        ^ = note: the matched value is of type `B<isize, usize>` = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~         B(isize::MIN..=isize::MAX, 1..=usize::MAX) => (), LL ~         B(_, _) => todo!(), | error[E0004]: non-exhaustive patterns: `B(_, _)` not covered --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:62:11 | LL |     match B(0isize, 0usize) { |           ^^^^^^^^^^^^^^^^^ pattern `B(_, _)` not covered | note: `B<isize, usize>` defined here --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:5:8 | LL | struct B<T, U>(T, U); |        ^ = note: the matched value is of type `B<isize, usize>` = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~         B(_, 1..=usize::MAX) => (), LL ~         B(_, _) => todo!(), | error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0004`. </ins>

LL | struct Foo { |        ^^^ = note: the matched value is of type `Foo` <ins> = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching </ins> help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~         Foo { first: false, second: Some([1, 2, 3, 4]) } => (),

LL | struct Foo(isize, isize); |        ^^^ = note: the matched value is of type `Foo` <ins> = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching </ins> help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~         Foo(2, b) => println!("{}", b),