Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions compiler/rustc_mir_build/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,10 @@ pub(crate) struct UnreachablePatternInner<'tcx> {
pub(crate) covered_by_many: Option<MultiSpan>,
#[suggestion("remove the match arm", code = "", applicability = "machine-applicable")]
pub(crate) suggest_remove: Option<Span>,
#[note(
"`#[non_exhaustive]` does not affect exhaustiveness checking within the defining crate"
)]
pub(crate) non_exhaustive_attr: Option<Span>,
}

#[derive(Subdiagnostic)]
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_mir_build/src/thir/pattern/check_match.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use rustc_arena::{DroplessArena, TypedArena};
use rustc_ast::Mutability;
use rustc_attr_ir::find_attr;
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::codes::*;
use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, msg, struct_span_code_err};
Expand Down Expand Up @@ -982,6 +983,7 @@ fn report_unreachable_pattern<'p, 'tcx>(
inaccessible_constant: None,
pattern_let_binding: None,
suggest_remove: None,
non_exhaustive_attr: None,
};
let mut covered_by_many_n_more_count = None;
match explanation.covered_by.as_slice() {
Expand Down Expand Up @@ -1031,6 +1033,16 @@ fn report_unreachable_pattern<'p, 'tcx>(
lint.covered_by_many = Some(multispan);
}
}

if let Constructor::Wildcard = pat.ctor()
&& let ty::Adt(adt, _) = pat.ty().peel_refs().kind()
&& adt.is_enum()
&& let Some(did) = adt.did().as_local()
&& let Some(span) = find_attr!(cx.tcx, did, NonExhaustive(span) => span)
{
lint.non_exhaustive_attr = Some(*span);
}

cx.tcx.emit_node_span_lint(
UNREACHABLE_PATTERNS,
hir_id,
Expand Down
53 changes: 53 additions & 0 deletions tests/ui/match/unreachable-pattern-with-non-exhaustive.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//@ aux-crate:upstream=match_non_exhaustive_lib.rs
//@ dont-require-annotations: NOTE
//@ edition: 2024

#![deny(unreachable_patterns)]

#[non_exhaustive]
//~^ NOTE `#[non_exhaustive]` does not affect exhaustiveness checking within the defining crate
//~| NOTE `#[non_exhaustive]` does not affect exhaustiveness checking within the defining crate
//~| NOTE `#[non_exhaustive]` does not affect exhaustiveness checking within the defining crate
//~| NOTE `#[non_exhaustive]` does not affect exhaustiveness checking within the defining crate
enum E1 { A, B }

fn foo(e: E1) {
match e {
E1::A | E1::B => {}
_ => {}
//~^ ERROR unreachable pattern
}
}

fn foo_ref(e: &E1) {
match e {
E1::A | E1::B => {}
_ => {}
//~^ ERROR unreachable pattern
}
}

fn foo_mut_ref(e: &mut E1) {
match e {
E1::A | E1::B => {}
_ => {}
//~^ ERROR unreachable pattern
}
}

fn bar(e: Option<E1>) {
match e {
Some(E1::A | E1::B | _) => {}
//~^ ERROR unreachable pattern
None => {}
}
}

fn baz(e: upstream::E2) {
match e {
upstream::E2::A | upstream::E2::B => {}
_ => {}
}
}

fn main() {}
69 changes: 69 additions & 0 deletions tests/ui/match/unreachable-pattern-with-non-exhaustive.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
error: unreachable pattern
--> $DIR/unreachable-pattern-with-non-exhaustive.rs:17:9
|
LL | E1::A | E1::B => {}
| ------------- matches all the relevant values
LL | _ => {}
| ^ no value can reach this
|
note: `#[non_exhaustive]` does not affect exhaustiveness checking within the defining crate
--> $DIR/unreachable-pattern-with-non-exhaustive.rs:7:1
|
LL | #[non_exhaustive]
| ^^^^^^^^^^^^^^^^^
note: the lint level is defined here
--> $DIR/unreachable-pattern-with-non-exhaustive.rs:5:9
|
LL | #![deny(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^

error: unreachable pattern
--> $DIR/unreachable-pattern-with-non-exhaustive.rs:25:9
|
LL | E1::A | E1::B => {}
| ------------- matches all the relevant values
LL | _ => {}
| ^ no value can reach this
|
note: `#[non_exhaustive]` does not affect exhaustiveness checking within the defining crate
--> $DIR/unreachable-pattern-with-non-exhaustive.rs:7:1
|
LL | #[non_exhaustive]
| ^^^^^^^^^^^^^^^^^

error: unreachable pattern
--> $DIR/unreachable-pattern-with-non-exhaustive.rs:33:9
|
LL | E1::A | E1::B => {}
| ------------- matches all the relevant values
LL | _ => {}
| ^ no value can reach this
|
note: `#[non_exhaustive]` does not affect exhaustiveness checking within the defining crate
--> $DIR/unreachable-pattern-with-non-exhaustive.rs:7:1
|
LL | #[non_exhaustive]
| ^^^^^^^^^^^^^^^^^

error: unreachable pattern
--> $DIR/unreachable-pattern-with-non-exhaustive.rs:40:30
|
LL | Some(E1::A | E1::B | _) => {}
| ^ no value can reach this
|
note: multiple earlier patterns match some of the same values
--> $DIR/unreachable-pattern-with-non-exhaustive.rs:40:30
|
LL | Some(E1::A | E1::B | _) => {}
| ----- ----- ^ collectively making this unreachable
| | |
| | matches some of the same values
| matches some of the same values
note: `#[non_exhaustive]` does not affect exhaustiveness checking within the defining crate
--> $DIR/unreachable-pattern-with-non-exhaustive.rs:7:1
|
LL | #[non_exhaustive]
| ^^^^^^^^^^^^^^^^^

error: aborting due to 4 previous errors

Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ LL | _ => {}
| help: remove the match arm
|
= note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
note: `#[non_exhaustive]` does not affect exhaustiveness checking within the defining crate
--> $DIR/enum_same_crate_empty_match.rs:24:1
|
LL | #[non_exhaustive]
| ^^^^^^^^^^^^^^^^^
note: the lint level is defined here
--> $DIR/enum_same_crate_empty_match.rs:3:9
|
Expand Down
Loading