diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 281f3ef6ef35a..dda4debecec67 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -325,9 +325,16 @@ mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = mir_build_union_pattern = cannot use unions in constant patterns +mir_build_unreachable_making_this_unreachable = collectively making this unreachable + +mir_build_unreachable_matches_same_values = matches some of the same values + mir_build_unreachable_pattern = unreachable pattern .label = unreachable pattern - .catchall_label = matches any value + .unreachable_matches_no_values = this pattern matches no values because `{$ty}` is uninhabited + .unreachable_covered_by_catchall = matches any value + .unreachable_covered_by_one = matches all the values already + .unreachable_covered_by_many = these patterns collectively make the last one unreachable mir_build_unsafe_fn_safe_body = an unsafe function restricts its caller, but its body is safe by default mir_build_unsafe_not_inherited = items do not inherit unsafety from separate enclosing items diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index f6f443b64a63a..bdc4b0ea97d18 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -582,11 +582,23 @@ pub(crate) struct NonConstPath { #[derive(LintDiagnostic)] #[diag(mir_build_unreachable_pattern)] -pub(crate) struct UnreachablePattern { +pub(crate) struct UnreachablePattern<'tcx> { #[label] pub(crate) span: Option, - #[label(mir_build_catchall_label)] - pub(crate) catchall: Option, + #[subdiagnostic] + pub(crate) matches_no_values: Option>, + #[label(mir_build_unreachable_covered_by_catchall)] + pub(crate) covered_by_catchall: Option, + #[label(mir_build_unreachable_covered_by_one)] + pub(crate) covered_by_one: Option, + #[note(mir_build_unreachable_covered_by_many)] + pub(crate) covered_by_many: Option, +} + +#[derive(Subdiagnostic)] +#[note(mir_build_unreachable_matches_no_values)] +pub(crate) struct UnreachableMatchesNoValues<'tcx> { + pub(crate) ty: Ty<'tcx>, } #[derive(Diagnostic)] diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 95799cec94b04..5e904057e732c 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -1,4 +1,5 @@ use crate::errors::*; +use crate::fluent_generated as fluent; use rustc_arena::{DroplessArena, TypedArena}; use rustc_ast::Mutability; @@ -16,8 +17,8 @@ use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; use rustc_pattern_analysis::errors::Uncovered; use rustc_pattern_analysis::rustc::{ - Constructor, DeconstructedPat, MatchArm, RevealedTy, RustcPatCtxt as PatCtxt, Usefulness, - UsefulnessReport, WitnessPat, + Constructor, DeconstructedPat, MatchArm, RedundancyExplanation, RevealedTy, + RustcPatCtxt as PatCtxt, Usefulness, UsefulnessReport, WitnessPat, }; use rustc_session::lint::builtin::{ BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS, @@ -391,12 +392,16 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { ) -> Result, ErrorGuaranteed> { let pattern_complexity_limit = get_limit_size(cx.tcx.hir().krate_attrs(), cx.tcx.sess, sym::pattern_complexity); - let report = - rustc_pattern_analysis::analyze_match(&cx, &arms, scrut_ty, pattern_complexity_limit) - .map_err(|err| { - self.error = Err(err); - err - })?; + let report = rustc_pattern_analysis::rustc::analyze_match( + &cx, + &arms, + scrut_ty, + pattern_complexity_limit, + ) + .map_err(|err| { + self.error = Err(err); + err + })?; // Warn unreachable subpatterns. for (arm, is_useful) in report.arm_usefulness.iter() { @@ -405,9 +410,9 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { { let mut redundant_subpats = redundant_subpats.clone(); // Emit lints in the order in which they occur in the file. - redundant_subpats.sort_unstable_by_key(|pat| pat.data().span); - for pat in redundant_subpats { - report_unreachable_pattern(cx, arm.arm_data, pat.data().span, None) + redundant_subpats.sort_unstable_by_key(|(pat, _)| pat.data().span); + for (pat, explanation) in redundant_subpats { + report_unreachable_pattern(cx, arm.arm_data, pat, &explanation) } } } @@ -906,26 +911,60 @@ fn report_irrefutable_let_patterns( fn report_unreachable_pattern<'p, 'tcx>( cx: &PatCtxt<'p, 'tcx>, hir_id: HirId, - span: Span, - catchall: Option, + pat: &DeconstructedPat<'p, 'tcx>, + explanation: &RedundancyExplanation<'p, 'tcx>, ) { - cx.tcx.emit_node_span_lint( - UNREACHABLE_PATTERNS, - hir_id, - span, - UnreachablePattern { span: if catchall.is_some() { Some(span) } else { None }, catchall }, - ); + let pat_span = pat.data().span; + let mut lint = UnreachablePattern { + span: Some(pat_span), + matches_no_values: None, + covered_by_catchall: None, + covered_by_one: None, + covered_by_many: None, + }; + match explanation.covered_by.as_slice() { + [] => { + // Empty pattern; we report the uninhabited type that caused the emptiness. + lint.span = None; // Don't label the pattern itself + pat.walk(&mut |subpat| { + let ty = **subpat.ty(); + if cx.is_uninhabited(ty) { + lint.matches_no_values = Some(UnreachableMatchesNoValues { ty }); + false // No need to dig further. + } else if matches!(subpat.ctor(), Constructor::Ref | Constructor::UnionField) { + false // Don't explore further since they are not by-value. + } else { + true + } + }); + } + [covering_pat] if pat_is_catchall(covering_pat) => { + lint.covered_by_catchall = Some(covering_pat.data().span); + } + [covering_pat] => { + lint.covered_by_one = Some(covering_pat.data().span); + } + covering_pats => { + let mut multispan = MultiSpan::from_span(pat_span); + for p in covering_pats { + multispan.push_span_label( + p.data().span, + fluent::mir_build_unreachable_matches_same_values, + ); + } + multispan + .push_span_label(pat_span, fluent::mir_build_unreachable_making_this_unreachable); + lint.covered_by_many = Some(multispan); + } + } + cx.tcx.emit_node_span_lint(UNREACHABLE_PATTERNS, hir_id, pat_span, lint); } /// Report unreachable arms, if any. fn report_arm_reachability<'p, 'tcx>(cx: &PatCtxt<'p, 'tcx>, report: &UsefulnessReport<'p, 'tcx>) { - let mut catchall = None; for (arm, is_useful) in report.arm_usefulness.iter() { - if matches!(is_useful, Usefulness::Redundant) { - report_unreachable_pattern(cx, arm.arm_data, arm.pat.data().span, catchall) - } - if !arm.has_guard && catchall.is_none() && pat_is_catchall(arm.pat) { - catchall = Some(arm.pat.data().span); + if let Usefulness::Redundant(explanation) = is_useful { + report_unreachable_pattern(cx, arm.arm_data, arm.pat, explanation) } } } diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 1b4bcb789d2da..a5c0b13c90be1 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -1,4 +1,6 @@ -//! Analysis of patterns, notably match exhaustiveness checking. +//! Analysis of patterns, notably match exhaustiveness checking. The main entrypoint for this crate +//! is [`usefulness::compute_match_usefulness`]. For rustc-specific types and entrypoints, see the +//! [`rustc`] module. // tidy-alphabetical-start #![allow(rustc::diagnostic_outside_of_impl)] @@ -23,14 +25,8 @@ use std::fmt; pub use rustc_index::{Idx, IndexVec}; // re-exported to avoid rustc_index version issues -#[cfg(feature = "rustc")] -use rustc_middle::ty::Ty; -#[cfg(feature = "rustc")] -use rustc_span::ErrorGuaranteed; - use crate::constructor::{Constructor, ConstructorSet, IntRange}; use crate::pat::DeconstructedPat; -use crate::pat_column::PatternColumn; pub trait Captures<'a> {} impl<'a, T: ?Sized> Captures<'a> for T {} @@ -128,30 +124,3 @@ impl<'p, Cx: PatCx> Clone for MatchArm<'p, Cx> { } impl<'p, Cx: PatCx> Copy for MatchArm<'p, Cx> {} - -/// The entrypoint for this crate. Computes whether a match is exhaustive and which of its arms are -/// useful, and runs some lints. -#[cfg(feature = "rustc")] -pub fn analyze_match<'p, 'tcx>( - tycx: &rustc::RustcPatCtxt<'p, 'tcx>, - arms: &[rustc::MatchArm<'p, 'tcx>], - scrut_ty: Ty<'tcx>, - pattern_complexity_limit: Option, -) -> Result, ErrorGuaranteed> { - use lints::lint_nonexhaustive_missing_variants; - use usefulness::{compute_match_usefulness, PlaceValidity}; - - let scrut_ty = tycx.reveal_opaque_ty(scrut_ty); - let scrut_validity = PlaceValidity::from_bool(tycx.known_valid_scrutinee); - let report = - compute_match_usefulness(tycx, arms, scrut_ty, scrut_validity, pattern_complexity_limit)?; - - // Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting - // `if let`s. Only run if the match is exhaustive otherwise the error is redundant. - if tycx.refutable && report.non_exhaustiveness_witnesses.is_empty() { - let pat_column = PatternColumn::new(arms); - lint_nonexhaustive_missing_variants(tycx, arms, &pat_column, scrut_ty)?; - } - - Ok(report) -} diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index e8d6c542c5fd4..a591c3c554b52 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -11,7 +11,7 @@ use crate::{PatCx, PrivateUninhabitedField}; use self::Constructor::*; /// A globally unique id to distinguish patterns. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub(crate) struct PatId(u32); impl PatId { fn new() -> Self { @@ -147,6 +147,21 @@ impl fmt::Debug for DeconstructedPat { } } +/// Delegate to `uid`. +impl PartialEq for DeconstructedPat { + fn eq(&self, other: &Self) -> bool { + self.uid == other.uid + } +} +/// Delegate to `uid`. +impl Eq for DeconstructedPat {} +/// Delegate to `uid`. +impl std::hash::Hash for DeconstructedPat { + fn hash(&self, state: &mut H) { + self.uid.hash(state); + } +} + /// Represents either a pattern obtained from user input or a wildcard constructed during the /// algorithm. Do not use `Wild` to represent a wildcard pattern comping from user input. /// diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 6ef2d69273ee7..910dd4c6c1a84 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -20,6 +20,9 @@ use rustc_target::abi::{FieldIdx, Integer, VariantIdx, FIRST_VARIANT}; use crate::constructor::{ IntRange, MaybeInfiniteInt, OpaqueId, RangeEnd, Slice, SliceKind, VariantVisibility, }; +use crate::lints::lint_nonexhaustive_missing_variants; +use crate::pat_column::PatternColumn; +use crate::usefulness::{compute_match_usefulness, PlaceValidity}; use crate::{errors, Captures, PatCx, PrivateUninhabitedField}; use crate::constructor::Constructor::*; @@ -29,6 +32,8 @@ pub type Constructor<'p, 'tcx> = crate::constructor::Constructor = crate::constructor::ConstructorSet>; pub type DeconstructedPat<'p, 'tcx> = crate::pat::DeconstructedPat>; pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcPatCtxt<'p, 'tcx>>; +pub type RedundancyExplanation<'p, 'tcx> = + crate::usefulness::RedundancyExplanation<'p, RustcPatCtxt<'p, 'tcx>>; pub type Usefulness<'p, 'tcx> = crate::usefulness::Usefulness<'p, RustcPatCtxt<'p, 'tcx>>; pub type UsefulnessReport<'p, 'tcx> = crate::usefulness::UsefulnessReport<'p, RustcPatCtxt<'p, 'tcx>>; @@ -1058,3 +1063,26 @@ fn expand_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> Vec<&'p Pat<'tcx>> { expand(pat, &mut pats); pats } + +/// The entrypoint for this crate. Computes whether a match is exhaustive and which of its arms are +/// useful, and runs some lints. +pub fn analyze_match<'p, 'tcx>( + tycx: &RustcPatCtxt<'p, 'tcx>, + arms: &[MatchArm<'p, 'tcx>], + scrut_ty: Ty<'tcx>, + pattern_complexity_limit: Option, +) -> Result, ErrorGuaranteed> { + let scrut_ty = tycx.reveal_opaque_ty(scrut_ty); + let scrut_validity = PlaceValidity::from_bool(tycx.known_valid_scrutinee); + let report = + compute_match_usefulness(tycx, arms, scrut_ty, scrut_validity, pattern_complexity_limit)?; + + // Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting + // `if let`s. Only run if the match is exhaustive otherwise the error is redundant. + if tycx.refutable && report.non_exhaustiveness_witnesses.is_empty() { + let pat_column = PatternColumn::new(arms); + lint_nonexhaustive_missing_variants(tycx, arms, &pat_column, scrut_ty)?; + } + + Ok(report) +} diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 8486792b5543f..76dc338e71cd3 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -713,7 +713,7 @@ use self::PlaceValidity::*; use crate::constructor::{Constructor, ConstructorSet, IntRange}; use crate::pat::{DeconstructedPat, PatId, PatOrWild, WitnessPat}; use crate::{Captures, MatchArm, PatCx, PrivateUninhabitedField}; -use rustc_hash::FxHashSet; +use rustc_hash::{FxHashMap, FxHashSet}; use rustc_index::bit_set::BitSet; use smallvec::{smallvec, SmallVec}; use std::fmt; @@ -726,18 +726,81 @@ pub fn ensure_sufficient_stack(f: impl FnOnce() -> R) -> R { f() } +/// A pattern is a "branch" if it is the immediate child of an or-pattern, or if it is the whole +/// pattern of a match arm. These are the patterns that can be meaningfully considered "redundant", +/// since e.g. `0` in `(0, 1)` cannot be redundant on its own. +/// +/// We track for each branch pattern whether it is useful, and if not why. +struct BranchPatUsefulness<'p, Cx: PatCx> { + /// Whether this pattern is useful. + useful: bool, + /// A set of patterns that: + /// - come before this one in the match; + /// - intersect this one; + /// - at the end of the algorithm, if `!self.useful`, their union covers this pattern. + covered_by: FxHashSet<&'p DeconstructedPat>, +} + +impl<'p, Cx: PatCx> BranchPatUsefulness<'p, Cx> { + /// Update `self` with the usefulness information found in `row`. + fn update(&mut self, row: &MatrixRow<'p, Cx>, matrix: &Matrix<'p, Cx>) { + self.useful |= row.useful; + // This deserves an explanation: `intersects_at_least` does not contain all intersections + // because we skip irrelevant values (see the docs for `intersects_at_least` for an + // example). Yet we claim this suffices to build a covering set. + // + // Let `p` be our pattern. Assume it is found not useful. For a value `v`, if the value was + // relevant then we explored that value and found that there was another pattern `q` before + // `p` that matches it too. We therefore recorded an intersection with `q`. If `v` was + // irrelevant, we know there's another value `v2` that matches strictly fewer rows (while + // still matching our row) and is relevant. Since `p` is not useful, there must have been a + // `q` before `p` that matches `v2`, and we recorded that intersection. Since `v2` matches + // strictly fewer rows than `v`, `q` also matches `v`. In either case, we recorded in + // `intersects_at_least` a pattern that matches `v`. Hence using `intersects_at_least` is + // sufficient to build a covering set. + for row_id in row.intersects_at_least.iter() { + let row = &matrix.rows[row_id]; + if row.useful && !row.is_under_guard { + if let PatOrWild::Pat(intersecting) = row.head() { + self.covered_by.insert(intersecting); + } + } + } + } + + /// Check whether this pattern is redundant, and if so explain why. + fn is_redundant(&self) -> Option> { + if self.useful { + None + } else { + // We avoid instability by sorting by `uid`. The order of `uid`s only depends on the + // pattern structure. + #[cfg_attr(feature = "rustc", allow(rustc::potential_query_instability))] + let mut covered_by: Vec<_> = self.covered_by.iter().copied().collect(); + covered_by.sort_by_key(|pat| pat.uid); // sort to avoid instability + Some(RedundancyExplanation { covered_by }) + } + } +} + +impl<'p, Cx: PatCx> Default for BranchPatUsefulness<'p, Cx> { + fn default() -> Self { + Self { useful: Default::default(), covered_by: Default::default() } + } +} + /// Context that provides information for usefulness checking. -struct UsefulnessCtxt<'a, Cx: PatCx> { +struct UsefulnessCtxt<'a, 'p, Cx: PatCx> { /// The context for type information. tycx: &'a Cx, - /// Collect the patterns found useful during usefulness checking. This is used to lint - /// unreachable (sub)patterns. - useful_subpatterns: FxHashSet, + /// Track information about the usefulness of branch patterns (see definition of "branch + /// pattern" at [`BranchPatUsefulness`]). + branch_usefulness: FxHashMap>, complexity_limit: Option, complexity_level: usize, } -impl<'a, Cx: PatCx> UsefulnessCtxt<'a, Cx> { +impl<'a, 'p, Cx: PatCx> UsefulnessCtxt<'a, 'p, Cx> { fn increase_complexity_level(&mut self, complexity_add: usize) -> Result<(), Cx::Error> { self.complexity_level += complexity_add; if self @@ -1051,14 +1114,40 @@ struct MatrixRow<'p, Cx: PatCx> { /// [`compute_exhaustiveness_and_usefulness`] if the arm is found to be useful. /// This is reset to `false` when specializing. useful: bool, - /// Tracks which rows above this one have an intersection with this one, i.e. such that there is - /// a value that matches both rows. - /// Note: Because of relevancy we may miss some intersections. The intersections we do find are - /// correct. - intersects: BitSet, + /// Tracks some rows above this one that have an intersection with this one, i.e. such that + /// there is a value that matches both rows. + /// Because of relevancy we may miss some intersections. The intersections we do find are + /// correct. In other words, this is an underapproximation of the real set of intersections. + /// + /// For example: + /// ```rust,ignore(illustrative) + /// match ... { + /// (true, _, _) => {} // `intersects_at_least = []` + /// (_, true, 0..=10) => {} // `intersects_at_least = []` + /// (_, true, 5..15) => {} // `intersects_at_least = [1]` + /// } + /// ``` + /// Here the `(true, true)` case is irrelevant. Since we skip it, we will not detect that row 0 + /// intersects rows 1 and 2. + intersects_at_least: BitSet, + /// Whether the head pattern is a branch (see definition of "branch pattern" at + /// [`BranchPatUsefulness`]) + head_is_branch: bool, } impl<'p, Cx: PatCx> MatrixRow<'p, Cx> { + fn new(arm: &MatchArm<'p, Cx>, arm_id: usize) -> Self { + MatrixRow { + pats: PatStack::from_pattern(arm.pat), + parent_row: arm_id, + is_under_guard: arm.has_guard, + useful: false, + intersects_at_least: BitSet::new_empty(0), // Initialized in `Matrix::push`. + // This pattern is a branch because it comes from a match arm. + head_is_branch: true, + } + } + fn len(&self) -> usize { self.pats.len() } @@ -1076,12 +1165,14 @@ impl<'p, Cx: PatCx> MatrixRow<'p, Cx> { &self, parent_row: usize, ) -> impl Iterator> + Captures<'_> { + let is_or_pat = self.pats.head().is_or_pat(); self.pats.expand_or_pat().map(move |patstack| MatrixRow { pats: patstack, parent_row, is_under_guard: self.is_under_guard, useful: false, - intersects: BitSet::new_empty(0), // Initialized in `Matrix::expand_and_push`. + intersects_at_least: BitSet::new_empty(0), // Initialized in `Matrix::push`. + head_is_branch: is_or_pat, }) } @@ -1100,7 +1191,8 @@ impl<'p, Cx: PatCx> MatrixRow<'p, Cx> { parent_row, is_under_guard: self.is_under_guard, useful: false, - intersects: BitSet::new_empty(0), // Initialized in `Matrix::push`. + intersects_at_least: BitSet::new_empty(0), // Initialized in `Matrix::push`. + head_is_branch: false, }) } } @@ -1138,7 +1230,7 @@ struct Matrix<'p, Cx: PatCx> { impl<'p, Cx: PatCx> Matrix<'p, Cx> { /// Pushes a new row to the matrix. Internal method, prefer [`Matrix::new`]. fn push(&mut self, mut row: MatrixRow<'p, Cx>) { - row.intersects = BitSet::new_empty(self.rows.len()); + row.intersects_at_least = BitSet::new_empty(self.rows.len()); self.rows.push(row); } @@ -1156,14 +1248,7 @@ impl<'p, Cx: PatCx> Matrix<'p, Cx> { wildcard_row_is_relevant: true, }; for (arm_id, arm) in arms.iter().enumerate() { - let v = MatrixRow { - pats: PatStack::from_pattern(arm.pat), - parent_row: arm_id, - is_under_guard: arm.has_guard, - useful: false, - intersects: BitSet::new_empty(0), // Initialized in `Matrix::push`. - }; - matrix.push(v); + matrix.push(MatrixRow::new(arm, arm_id)); } matrix } @@ -1242,12 +1327,12 @@ impl<'p, Cx: PatCx> Matrix<'p, Cx> { let parent_row = &mut self.rows[parent_row_id]; // A parent row is useful if any of its children is. parent_row.useful |= child_row.useful; - for child_intersection in child_row.intersects.iter() { + for child_intersection in child_row.intersects_at_least.iter() { // Convert the intersecting ids into ids for the parent matrix. let parent_intersection = specialized.rows[child_intersection].parent_row; // Note: self-intersection can happen with or-patterns. if parent_intersection != parent_row_id { - parent_row.intersects.insert(parent_intersection); + parent_row.intersects_at_least.insert(parent_intersection); } } } @@ -1544,7 +1629,7 @@ fn collect_overlapping_range_endpoints<'p, Cx: PatCx>( let overlaps_with: Vec<_> = prefixes .iter() .filter(|&&(other_child_row_id, _)| { - child_row.intersects.contains(other_child_row_id) + child_row.intersects_at_least.contains(other_child_row_id) }) .map(|&(_, pat)| pat) .collect(); @@ -1560,7 +1645,7 @@ fn collect_overlapping_range_endpoints<'p, Cx: PatCx>( let overlaps_with: Vec<_> = suffixes .iter() .filter(|&&(other_child_row_id, _)| { - child_row.intersects.contains(other_child_row_id) + child_row.intersects_at_least.contains(other_child_row_id) }) .map(|&(_, pat)| pat) .collect(); @@ -1603,8 +1688,8 @@ fn collect_non_contiguous_range_endpoints<'p, Cx: PatCx>( /// The core of the algorithm. /// /// This recursively computes witnesses of the non-exhaustiveness of `matrix` (if any). Also tracks -/// usefulness of each row in the matrix (in `row.useful`). We track usefulness of each subpattern -/// in `mcx.useful_subpatterns`. +/// usefulness of each row in the matrix (in `row.useful`). We track usefulness of subpatterns in +/// `mcx.branch_usefulness`. /// /// The input `Matrix` and the output `WitnessMatrix` together match the type exhaustively. /// @@ -1616,7 +1701,7 @@ fn collect_non_contiguous_range_endpoints<'p, Cx: PatCx>( /// This is all explained at the top of the file. #[instrument(level = "debug", skip(mcx), ret)] fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: PatCx>( - mcx: &mut UsefulnessCtxt<'a, Cx>, + mcx: &mut UsefulnessCtxt<'a, 'p, Cx>, matrix: &mut Matrix<'p, Cx>, ) -> Result, Cx::Error> { debug_assert!(matrix.rows().all(|r| r.len() == matrix.column_count())); @@ -1635,7 +1720,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: PatCx>( let mut useful = true; // Whether the next row is useful. for (i, row) in matrix.rows_mut().enumerate() { row.useful = useful; - row.intersects.insert_range(0..i); + row.intersects_at_least.insert_range(0..i); // The next rows stays useful if this one is under a guard. useful &= row.is_under_guard; } @@ -1677,7 +1762,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: PatCx>( if let Constructor::IntRange(overlap_range) = ctor { if overlap_range.is_singleton() && spec_matrix.rows.len() >= 2 - && spec_matrix.rows.iter().any(|row| !row.intersects.is_empty()) + && spec_matrix.rows.iter().any(|row| !row.intersects_at_least.is_empty()) { collect_overlapping_range_endpoints(mcx.tycx, overlap_range, matrix, &spec_matrix); } @@ -1697,14 +1782,11 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: PatCx>( } } - // Record usefulness in the patterns. + // Record usefulness of the branch patterns. for row in matrix.rows() { - if row.useful { + if row.head_is_branch { if let PatOrWild::Pat(pat) = row.head() { - let newly_useful = mcx.useful_subpatterns.insert(pat.uid); - if newly_useful { - debug!("newly useful: {pat:?}"); - } + mcx.branch_usefulness.entry(pat.uid).or_default().update(row, matrix); } } } @@ -1712,16 +1794,25 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: PatCx>( Ok(ret) } +/// Indicates why a given pattern is considered redundant. +#[derive(Clone, Debug)] +pub struct RedundancyExplanation<'p, Cx: PatCx> { + /// All the values matched by this pattern are already matched by the given set of patterns. + /// This list is not guaranteed to be minimal but the contained patterns are at least guaranteed + /// to intersect this pattern. + pub covered_by: Vec<&'p DeconstructedPat>, +} + /// Indicates whether or not a given arm is useful. #[derive(Clone, Debug)] pub enum Usefulness<'p, Cx: PatCx> { /// The arm is useful. This additionally carries a set of or-pattern branches that have been /// found to be redundant despite the overall arm being useful. Used only in the presence of /// or-patterns, otherwise it stays empty. - Useful(Vec<&'p DeconstructedPat>), + Useful(Vec<(&'p DeconstructedPat, RedundancyExplanation<'p, Cx>)>), /// The arm is redundant and can be removed without changing the behavior of the match /// expression. - Redundant, + Redundant(RedundancyExplanation<'p, Cx>), } /// The output of checking a match for exhaustiveness and arm usefulness. @@ -1747,7 +1838,7 @@ pub fn compute_match_usefulness<'p, Cx: PatCx>( ) -> Result, Cx::Error> { let mut cx = UsefulnessCtxt { tycx, - useful_subpatterns: FxHashSet::default(), + branch_usefulness: FxHashMap::default(), complexity_limit, complexity_level: 0, }; @@ -1760,26 +1851,32 @@ pub fn compute_match_usefulness<'p, Cx: PatCx>( .copied() .map(|arm| { debug!(?arm); - let usefulness = if cx.useful_subpatterns.contains(&arm.pat.uid) { + let usefulness = cx.branch_usefulness.get(&arm.pat.uid).unwrap(); + let usefulness = if let Some(explanation) = usefulness.is_redundant() { + Usefulness::Redundant(explanation) + } else { let mut redundant_subpats = Vec::new(); arm.pat.walk(&mut |subpat| { - if cx.useful_subpatterns.contains(&subpat.uid) { - true // keep recursing + if let Some(u) = cx.branch_usefulness.get(&subpat.uid) { + if let Some(explanation) = u.is_redundant() { + redundant_subpats.push((subpat, explanation)); + false // stop recursing + } else { + true // keep recursing + } } else { - redundant_subpats.push(subpat); - false // stop recursing + true // keep recursing } }); Usefulness::Useful(redundant_subpats) - } else { - Usefulness::Redundant }; debug!(?usefulness); (arm, usefulness) }) .collect(); - let arm_intersections: Vec<_> = matrix.rows().map(|row| row.intersects.clone()).collect(); + let arm_intersections: Vec<_> = + matrix.rows().map(|row| row.intersects_at_least.clone()).collect(); Ok(UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses, arm_intersections }) } diff --git a/compiler/rustc_pattern_analysis/tests/common/mod.rs b/compiler/rustc_pattern_analysis/tests/common/mod.rs index 6e8bb50500554..68ec75b770533 100644 --- a/compiler/rustc_pattern_analysis/tests/common/mod.rs +++ b/compiler/rustc_pattern_analysis/tests/common/mod.rs @@ -25,7 +25,7 @@ pub fn init_tracing() { /// A simple set of types. #[allow(dead_code)] -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum Ty { /// Booleans Bool, @@ -33,6 +33,8 @@ pub enum Ty { U8, /// Tuples. Tuple(&'static [Ty]), + /// Enum with one variant of each given type. + Enum(&'static [Ty]), /// A struct with `arity` fields of type `ty`. BigStruct { arity: usize, ty: &'static Ty }, /// A enum with `arity` variants of type `ty`. @@ -46,12 +48,23 @@ impl Ty { match (ctor, *self) { (Struct, Ty::Tuple(tys)) => tys.iter().copied().collect(), (Struct, Ty::BigStruct { arity, ty }) => (0..arity).map(|_| *ty).collect(), + (Variant(i), Ty::Enum(tys)) => vec![tys[*i]], (Variant(_), Ty::BigEnum { ty, .. }) => vec![*ty], (Bool(..) | IntRange(..) | NonExhaustive | Missing | Wildcard, _) => vec![], _ => panic!("Unexpected ctor {ctor:?} for type {self:?}"), } } + fn is_empty(&self) -> bool { + match *self { + Ty::Bool | Ty::U8 => false, + Ty::Tuple(tys) => tys.iter().any(|ty| ty.is_empty()), + Ty::Enum(tys) => tys.iter().all(|ty| ty.is_empty()), + Ty::BigStruct { arity, ty } => arity != 0 && ty.is_empty(), + Ty::BigEnum { arity, ty } => arity == 0 || ty.is_empty(), + } + } + pub fn ctor_set(&self) -> ConstructorSet { match *self { Ty::Bool => ConstructorSet::Bool, @@ -64,10 +77,32 @@ impl Ty { range_2: None, }, Ty::Tuple(..) | Ty::BigStruct { .. } => ConstructorSet::Struct { empty: false }, - Ty::BigEnum { arity, .. } => ConstructorSet::Variants { - variants: (0..arity).map(|_| VariantVisibility::Visible).collect(), + Ty::Enum(tys) if tys.is_empty() => ConstructorSet::NoConstructors, + Ty::Enum(tys) => ConstructorSet::Variants { + variants: tys + .iter() + .map(|ty| { + if ty.is_empty() { + VariantVisibility::Empty + } else { + VariantVisibility::Visible + } + }) + .collect(), non_exhaustive: false, }, + Ty::BigEnum { arity: 0, .. } => ConstructorSet::NoConstructors, + Ty::BigEnum { arity, ty } => { + let vis = if ty.is_empty() { + VariantVisibility::Empty + } else { + VariantVisibility::Visible + }; + ConstructorSet::Variants { + variants: (0..arity).map(|_| vis).collect(), + non_exhaustive: false, + } + } } } @@ -79,6 +114,7 @@ impl Ty { match (*self, ctor) { (Ty::Tuple(..), _) => Ok(()), (Ty::BigStruct { .. }, _) => write!(f, "BigStruct"), + (Ty::Enum(..), Constructor::Variant(i)) => write!(f, "Enum::Variant{i}"), (Ty::BigEnum { .. }, Constructor::Variant(i)) => write!(f, "BigEnum::Variant{i}"), _ => write!(f, "{:?}::{:?}", self, ctor), } @@ -119,7 +155,7 @@ impl PatCx for Cx { } fn is_min_exhaustive_patterns_feature_on(&self) -> bool { - false + true } fn ctor_arity(&self, ctor: &Constructor, ty: &Self::Ty) -> usize { diff --git a/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs b/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs index 4f8d68d5514be..205d430d49509 100644 --- a/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs +++ b/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs @@ -76,3 +76,17 @@ fn test_nested() { Struct(Variant.1, Variant.1), )); } + +#[test] +fn test_empty() { + // `TY = Result` + const TY: Ty = Ty::Enum(&[Ty::Bool, Ty::Enum(&[])]); + assert_exhaustive(pats!(TY; + Variant.0, + )); + let ty = Ty::Tuple(&[Ty::Bool, TY]); + assert_exhaustive(pats!(ty; + (true, Variant.0), + (false, Variant.0), + )); +} diff --git a/compiler/rustc_pattern_analysis/tests/intersection.rs b/compiler/rustc_pattern_analysis/tests/intersection.rs index 4a96b7248dae6..8c8cb3c796d8b 100644 --- a/compiler/rustc_pattern_analysis/tests/intersection.rs +++ b/compiler/rustc_pattern_analysis/tests/intersection.rs @@ -67,4 +67,24 @@ fn test_nested() { ), &[&[], &[]], ); + let ty = Ty::Tuple(&[Ty::Bool; 3]); + assert_intersects( + pats!(ty; + (true, true, _), + (true, _, true), + (false, _, _), + ), + &[&[], &[], &[]], + ); + let ty = Ty::Tuple(&[Ty::Bool, Ty::Bool, Ty::U8]); + assert_intersects( + pats!(ty; + (true, _, _), + (_, true, 0..10), + (_, true, 10..), + (_, true, 3), + _, + ), + &[&[], &[], &[], &[1], &[0, 1, 2, 3]], + ); } diff --git a/tests/ui/consts/packed_pattern.stderr b/tests/ui/consts/packed_pattern.stderr index 9ca50a95e4e41..a0b434b2d78ee 100644 --- a/tests/ui/consts/packed_pattern.stderr +++ b/tests/ui/consts/packed_pattern.stderr @@ -1,8 +1,10 @@ warning: unreachable pattern --> $DIR/packed_pattern.rs:16:9 | +LL | Foo { field: (5, 6, 7, 8) } => {}, + | --------------------------- matches all the values already LL | FOO => unreachable!(), - | ^^^ + | ^^^ unreachable pattern | = note: `#[warn(unreachable_patterns)]` on by default diff --git a/tests/ui/consts/packed_pattern2.stderr b/tests/ui/consts/packed_pattern2.stderr index 4dc54461eeb24..4785f4d029721 100644 --- a/tests/ui/consts/packed_pattern2.stderr +++ b/tests/ui/consts/packed_pattern2.stderr @@ -1,8 +1,10 @@ warning: unreachable pattern --> $DIR/packed_pattern2.rs:24:9 | +LL | Bar { a: Foo { field: (5, 6) } } => {}, + | -------------------------------- matches all the values already LL | FOO => unreachable!(), - | ^^^ + | ^^^ unreachable pattern | = note: `#[warn(unreachable_patterns)]` on by default diff --git a/tests/ui/error-codes/E0001.stderr b/tests/ui/error-codes/E0001.stderr index 49bb73e7ba866..40008230ec801 100644 --- a/tests/ui/error-codes/E0001.stderr +++ b/tests/ui/error-codes/E0001.stderr @@ -2,8 +2,17 @@ error: unreachable pattern --> $DIR/E0001.rs:8:9 | LL | _ => {/* ... */} - | ^ + | ^ unreachable pattern | +note: these patterns collectively make the last one unreachable + --> $DIR/E0001.rs:8:9 + | +LL | Some(_) => {/* ... */} + | ------- matches some of the same values +LL | None => {/* ... */} + | ---- matches some of the same values +LL | _ => {/* ... */} + | ^ collectively making this unreachable note: the lint level is defined here --> $DIR/E0001.rs:1:9 | diff --git a/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.rs b/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.rs index 1ad335bf39481..afdcff0346bb2 100644 --- a/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.rs +++ b/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.rs @@ -29,6 +29,11 @@ fn main() { (1, 4 | 5) => {} //~ ERROR unreachable pattern _ => {} } + match (0u8, 0u8, 0u8) { + (0, 0, 0) => {} + (0, 0 | 1, 0) => {} //~ ERROR unreachable pattern + _ => {} + } match (true, true) { (false | true, false | true) => (), } diff --git a/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr b/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr index 336530d1b320a..5570390b21c28 100644 --- a/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr +++ b/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr @@ -1,8 +1,10 @@ error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:8:9 | +LL | (1 | 2,) => {} + | -------- matches all the values already LL | (1,) => {} - | ^^^^ + | ^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/exhaustiveness-unreachable-pattern.rs:1:9 @@ -13,212 +15,354 @@ LL | #![deny(unreachable_patterns)] error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:13:9 | +LL | (1 | 2,) => {} + | -------- matches all the values already LL | (2,) => {} - | ^^^^ + | ^^^^ unreachable pattern error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:19:9 | LL | (1 | 2,) => {} - | ^^^^^^^^ + | ^^^^^^^^ unreachable pattern + | +note: these patterns collectively make the last one unreachable + --> $DIR/exhaustiveness-unreachable-pattern.rs:19:9 + | +LL | (1,) => {} + | ---- matches some of the same values +LL | (2,) => {} + | ---- matches some of the same values +LL | (1 | 2,) => {} + | ^^^^^^^^ collectively making this unreachable error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:24:9 | +LL | (1 | 2, 3 | 4) => {} + | -------------- matches all the values already LL | (1, 3) => {} - | ^^^^^^ + | ^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:25:9 | +LL | (1 | 2, 3 | 4) => {} + | -------------- matches all the values already +LL | (1, 3) => {} LL | (1, 4) => {} - | ^^^^^^ + | ^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:26:9 | +LL | (1 | 2, 3 | 4) => {} + | -------------- matches all the values already +... LL | (2, 4) => {} - | ^^^^^^ + | ^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:27:9 | +LL | (1 | 2, 3 | 4) => {} + | -------------- matches all the values already +... LL | (2 | 1, 4) => {} - | ^^^^^^^^^^ + | ^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:29:9 | LL | (1, 4 | 5) => {} - | ^^^^^^^^^^ + | ^^^^^^^^^^ unreachable pattern + | +note: these patterns collectively make the last one unreachable + --> $DIR/exhaustiveness-unreachable-pattern.rs:29:9 + | +LL | (1 | 2, 3 | 4) => {} + | -------------- matches some of the same values +... +LL | (1, 5 | 6) => {} + | ---------- matches some of the same values +LL | (1, 4 | 5) => {} + | ^^^^^^^^^^ collectively making this unreachable error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:37:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:34:13 | +LL | (0, 0, 0) => {} + | - matches all the values already +LL | (0, 0 | 1, 0) => {} + | ^ unreachable pattern + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:42:9 + | +LL | (None | Some(1 | 2),) => {} + | --------------------- matches all the values already LL | (Some(1),) => {} - | ^^^^^^^^^^ + | ^^^^^^^^^^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:38:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:43:9 | +LL | (None | Some(1 | 2),) => {} + | --------------------- matches all the values already +LL | (Some(1),) => {} LL | (None,) => {} - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:43:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:48:9 | +LL | ((1 | 2,) | (3 | 4,),) => {} + | ---------------------- matches all the values already LL | ((1..=4,),) => {} - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:48:14 + --> $DIR/exhaustiveness-unreachable-pattern.rs:53:14 | LL | (1 | 1,) => {} - | ^ + | - ^ unreachable pattern + | | + | matches all the values already error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:52:19 + --> $DIR/exhaustiveness-unreachable-pattern.rs:57:19 | LL | (0 | 1) | 1 => {} - | ^ + | - ^ unreachable pattern + | | + | matches all the values already error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:58:14 + --> $DIR/exhaustiveness-unreachable-pattern.rs:63:14 | LL | 0 | (0 | 0) => {} - | ^ + | - ^ unreachable pattern + | | + | matches all the values already error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:58:18 + --> $DIR/exhaustiveness-unreachable-pattern.rs:63:18 | LL | 0 | (0 | 0) => {} - | ^ + | - ^ unreachable pattern + | | + | matches all the values already error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:66:13 + --> $DIR/exhaustiveness-unreachable-pattern.rs:71:13 | +LL | Some(0) | + | ------- matches all the values already LL | / Some( LL | | 0 | 0) => {} - | |______________________^ + | |______________________^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:72:15 + --> $DIR/exhaustiveness-unreachable-pattern.rs:77:15 | +LL | [0 + | - matches all the values already LL | | 0 - | ^ + | ^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:74:15 + --> $DIR/exhaustiveness-unreachable-pattern.rs:79:15 | +LL | , 0 + | - matches all the values already LL | | 0] => {} - | ^ + | ^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:78:20 + --> $DIR/exhaustiveness-unreachable-pattern.rs:83:20 | LL | (true, 0 | 0) => {} - | ^ + | - ^ unreachable pattern + | | + | matches all the values already error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:79:17 + --> $DIR/exhaustiveness-unreachable-pattern.rs:84:17 | LL | (_, 0 | 0) => {} - | ^ + | ^ unreachable pattern + | +note: these patterns collectively make the last one unreachable + --> $DIR/exhaustiveness-unreachable-pattern.rs:84:17 + | +LL | (true, 0 | 0) => {} + | - matches some of the same values +LL | (_, 0 | 0) => {} + | - ^ collectively making this unreachable + | | + | matches some of the same values error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:87:10 + --> $DIR/exhaustiveness-unreachable-pattern.rs:92:10 | +LL | [1, ..] => {} + | - matches all the values already LL | [1 - | ^ + | ^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:99:10 + --> $DIR/exhaustiveness-unreachable-pattern.rs:104:10 | +LL | [true, ..] => {} + | ---- matches all the values already LL | [true - | ^^^^ + | ^^^^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:106:36 + --> $DIR/exhaustiveness-unreachable-pattern.rs:111:36 | LL | (true | false, None | Some(true - | ^^^^ + | ^^^^ unreachable pattern + | +note: these patterns collectively make the last one unreachable + --> $DIR/exhaustiveness-unreachable-pattern.rs:111:36 + | +LL | (true, Some(_)) => {} + | - matches some of the same values +LL | (false, Some(true)) => {} + | ---- matches some of the same values +LL | (true | false, None | Some(true + | ^^^^ collectively making this unreachable error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:111:14 + --> $DIR/exhaustiveness-unreachable-pattern.rs:116:14 | LL | (true - | ^^^^ + | ^^^^ unreachable pattern ... LL | (true | false, None | Some(t_or_f!())) => {} | --------- in this macro invocation | +note: these patterns collectively make the last one unreachable + --> $DIR/exhaustiveness-unreachable-pattern.rs:116:14 + | +LL | (true + | ^^^^ collectively making this unreachable +... +LL | (true, Some(_)) => {} + | - matches some of the same values +LL | (false, Some(true)) => {} + | ---- matches some of the same values +LL | (true | false, None | Some(t_or_f!())) => {} + | --------- in this macro invocation = note: this error originates in the macro `t_or_f` (in Nightly builds, run with -Z macro-backtrace for more info) error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:122:14 + --> $DIR/exhaustiveness-unreachable-pattern.rs:127:14 | +LL | Some(0) => {} + | - matches all the values already LL | Some(0 - | ^ + | ^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:141:19 + --> $DIR/exhaustiveness-unreachable-pattern.rs:146:19 | +LL | Some(false) => {} + | ----- matches all the values already +LL | None | Some(true LL | | false) => {} - | ^^^^^ + | ^^^^^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:149:15 + --> $DIR/exhaustiveness-unreachable-pattern.rs:154:15 | LL | | true) => {} - | ^^^^ + | ^^^^ unreachable pattern + | +note: these patterns collectively make the last one unreachable + --> $DIR/exhaustiveness-unreachable-pattern.rs:154:15 + | +LL | (false, true) => {} + | ---- matches some of the same values +LL | (true, true) => {} + | ---- matches some of the same values +LL | (false | true, false +LL | | true) => {} + | ^^^^ collectively making this unreachable error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:155:15 + --> $DIR/exhaustiveness-unreachable-pattern.rs:160:15 | LL | | true, - | ^^^^ + | ^^^^ unreachable pattern + | +note: these patterns collectively make the last one unreachable + --> $DIR/exhaustiveness-unreachable-pattern.rs:160:15 + | +LL | (true, false) => {} + | ---- matches some of the same values +LL | (true, true) => {} + | ---- matches some of the same values +LL | (false +LL | | true, + | ^^^^ collectively making this unreachable error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:160:15 + --> $DIR/exhaustiveness-unreachable-pattern.rs:165:15 | +LL | (x, y) + | ------ matches any value LL | | (y, x) => {} - | ^^^^^^ + | ^^^^^^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:164:30 + --> $DIR/exhaustiveness-unreachable-pattern.rs:169:30 | LL | fn unreachable_in_param((_ | (_, _)): (bool, bool)) {} - | ^^^^^^ + | - ^^^^^^ unreachable pattern + | | + | matches any value error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:171:14 + --> $DIR/exhaustiveness-unreachable-pattern.rs:176:14 | LL | let (_ | (_, _)) = bool_pair; - | ^^^^^^ + | - ^^^^^^ unreachable pattern + | | + | matches any value error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:173:14 + --> $DIR/exhaustiveness-unreachable-pattern.rs:178:14 | LL | for (_ | (_, _)) in [bool_pair] {} - | ^^^^^^ + | - ^^^^^^ unreachable pattern + | | + | matches any value error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:176:20 + --> $DIR/exhaustiveness-unreachable-pattern.rs:181:20 | LL | let (Some(_) | Some(true)) = bool_option else { return }; - | ^^^^^^^^^^ + | ------- ^^^^^^^^^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:178:22 + --> $DIR/exhaustiveness-unreachable-pattern.rs:183:22 | LL | if let Some(_) | Some(true) = bool_option {} - | ^^^^^^^^^^ + | ------- ^^^^^^^^^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:180:25 + --> $DIR/exhaustiveness-unreachable-pattern.rs:185:25 | LL | while let Some(_) | Some(true) = bool_option {} - | ^^^^^^^^^^ + | ------- ^^^^^^^^^^ unreachable pattern + | | + | matches all the values already -error: aborting due to 35 previous errors +error: aborting due to 36 previous errors diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr index d057309e42061..9d3a35321caf0 100644 --- a/tests/ui/pattern/usefulness/consts-opaque.stderr +++ b/tests/ui/pattern/usefulness/consts-opaque.stderr @@ -106,20 +106,34 @@ LL | _ => {} // should not be emitting unreachable warning error: unreachable pattern --> $DIR/consts-opaque.rs:72:9 | +LL | BAZ => {} + | --- matches all the values already LL | Baz::Baz1 => {} // should not be emitting unreachable warning - | ^^^^^^^^^ + | ^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/consts-opaque.rs:79:9 | +LL | Baz::Baz1 => {} + | --------- matches all the values already LL | BAZ => {} - | ^^^ + | ^^^ unreachable pattern error: unreachable pattern --> $DIR/consts-opaque.rs:87:9 | LL | _ => {} // should not be emitting unreachable warning - | ^ + | ^ unreachable pattern + | +note: these patterns collectively make the last one unreachable + --> $DIR/consts-opaque.rs:87:9 + | +LL | BAZ => {} + | --- matches some of the same values +LL | Baz::Baz2 => {} + | --------- matches some of the same values +LL | _ => {} // should not be emitting unreachable warning + | ^ collectively making this unreachable error: aborting due to 17 previous errors diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr index 4c43419243190..9e700ee55ef52 100644 --- a/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr @@ -4,6 +4,7 @@ error: unreachable pattern LL | _ => {} | ^ | + = note: this pattern matches no values because `EmptyEnum` is uninhabited note: the lint level is defined here --> $DIR/empty-match-check-notes.rs:7:9 | @@ -11,25 +12,31 @@ LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/empty-match-check-notes.rs:20:9 + --> $DIR/empty-match-check-notes.rs:21:9 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `EmptyEnum` is uninhabited error: unreachable pattern - --> $DIR/empty-match-check-notes.rs:27:9 + --> $DIR/empty-match-check-notes.rs:29:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `EmptyForeignEnum` is uninhabited error: unreachable pattern - --> $DIR/empty-match-check-notes.rs:30:9 + --> $DIR/empty-match-check-notes.rs:33:9 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `EmptyForeignEnum` is uninhabited error[E0005]: refutable pattern in local binding - --> $DIR/empty-match-check-notes.rs:35:9 + --> $DIR/empty-match-check-notes.rs:39:9 | LL | let None = x; | ^^^^ pattern `Some(_)` not covered @@ -44,7 +51,7 @@ LL | if let None = x { todo!() }; | ++ +++++++++++ error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered - --> $DIR/empty-match-check-notes.rs:45:11 + --> $DIR/empty-match-check-notes.rs:49:11 | LL | match 0u8 { | ^^^ pattern `0_u8..=u8::MAX` not covered diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr index 45f715dc7b2dc..480ae7095a6c2 100644 --- a/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr @@ -4,6 +4,7 @@ error: unreachable pattern LL | _ => {} | ^ | + = note: this pattern matches no values because `EmptyEnum` is uninhabited note: the lint level is defined here --> $DIR/empty-match-check-notes.rs:7:9 | @@ -11,25 +12,31 @@ LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/empty-match-check-notes.rs:20:9 + --> $DIR/empty-match-check-notes.rs:21:9 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `EmptyEnum` is uninhabited error: unreachable pattern - --> $DIR/empty-match-check-notes.rs:27:9 + --> $DIR/empty-match-check-notes.rs:29:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `EmptyForeignEnum` is uninhabited error: unreachable pattern - --> $DIR/empty-match-check-notes.rs:30:9 + --> $DIR/empty-match-check-notes.rs:33:9 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `EmptyForeignEnum` is uninhabited error[E0005]: refutable pattern in local binding - --> $DIR/empty-match-check-notes.rs:35:9 + --> $DIR/empty-match-check-notes.rs:39:9 | LL | let None = x; | ^^^^ pattern `Some(_)` not covered @@ -43,7 +50,7 @@ LL | if let None = x { todo!() }; | ++ +++++++++++ error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered - --> $DIR/empty-match-check-notes.rs:45:11 + --> $DIR/empty-match-check-notes.rs:49:11 | LL | match 0u8 { | ^^^ pattern `0_u8..=u8::MAX` not covered diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.rs b/tests/ui/pattern/usefulness/empty-match-check-notes.rs index ea797bc7dd5a3..2eef283a21e45 100644 --- a/tests/ui/pattern/usefulness/empty-match-check-notes.rs +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.rs @@ -15,9 +15,11 @@ fn empty_enum(x: EmptyEnum) { match x {} // ok match x { _ => {} //~ ERROR unreachable pattern + //~^ NOTE matches no values } match x { _ if false => {} //~ ERROR unreachable pattern + //~^ NOTE matches no values } } @@ -25,9 +27,11 @@ fn empty_foreign_enum(x: empty::EmptyForeignEnum) { match x {} // ok match x { _ => {} //~ ERROR unreachable pattern + //~^ NOTE matches no values } match x { _ if false => {} //~ ERROR unreachable pattern + //~^ NOTE matches no values } } diff --git a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr index 45bdba94d785f..416a50b87b594 100644 --- a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr @@ -4,6 +4,7 @@ error: unreachable pattern LL | _ => {} | ^ | + = note: this pattern matches no values because `!` is uninhabited note: the lint level is defined here --> $DIR/empty-types.rs:17:9 | @@ -15,6 +16,8 @@ error: unreachable pattern | LL | _x => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: type `&!` is non-empty --> $DIR/empty-types.rs:58:11 @@ -36,24 +39,32 @@ error: unreachable pattern | LL | (_, _) => {} | ^^^^^^ + | + = note: this pattern matches no values because `(u32, !)` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:80:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `(!, !)` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:83:9 | LL | (_, _) => {} | ^^^^^^ + | + = note: this pattern matches no values because `(!, !)` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:87:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: `Ok(_)` not covered --> $DIR/empty-types.rs:91:11 @@ -79,12 +90,16 @@ error: unreachable pattern | LL | Err(_) => {} | ^^^^^^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:104:9 | LL | Err(_) => {} | ^^^^^^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered --> $DIR/empty-types.rs:101:11 @@ -123,114 +138,152 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:123:9 | LL | Ok(_) => {} | ^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:126:9 | LL | Ok(_) => {} | ^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:127:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:130:9 | LL | Ok(_) => {} | ^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:131:9 | LL | Err(_) => {} | ^^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:140:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:143:13 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:152:13 | LL | Some(_) => {} | ^^^^^^^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:156:13 | +LL | None => {} + | ---- matches all the values already LL | _ => {} - | ^ + | ^ unreachable pattern error: unreachable pattern --> $DIR/empty-types.rs:208:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:213:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:218:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:223:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:229:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:288:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:291:9 | LL | (_, _) => {} | ^^^^^^ + | + = note: this pattern matches no values because `(!, !)` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:294:9 | LL | Ok(_) => {} | ^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:295:9 | LL | Err(_) => {} | ^^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty --> $DIR/empty-types.rs:327:11 @@ -292,18 +345,24 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `[!; 3]` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:372:9 | LL | [_, _, _] => {} | ^^^^^^^^^ + | + = note: this pattern matches no values because `[!; 3]` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:375:9 | LL | [_, ..] => {} | ^^^^^^^ + | + = note: this pattern matches no values because `[!; 3]` is uninhabited error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty --> $DIR/empty-types.rs:389:11 @@ -322,8 +381,10 @@ LL + } error: unreachable pattern --> $DIR/empty-types.rs:396:9 | +LL | [] => {} + | -- matches all the values already LL | _ => {} - | ^ + | ^ unreachable pattern error[E0004]: non-exhaustive patterns: `[]` not covered --> $DIR/empty-types.rs:398:11 @@ -344,48 +405,66 @@ error: unreachable pattern | LL | Some(_) => {} | ^^^^^^^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:422:9 | LL | Some(_a) => {} | ^^^^^^^^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:427:9 | +LL | None => {} + | ---- matches all the values already +LL | // !useful, !reachable LL | _ => {} - | ^ + | ^ unreachable pattern error: unreachable pattern --> $DIR/empty-types.rs:432:9 | +LL | None => {} + | ---- matches all the values already +LL | // !useful, !reachable LL | _a => {} - | ^^ + | ^^ unreachable pattern error: unreachable pattern --> $DIR/empty-types.rs:604:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:607:9 | LL | _x => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:610:9 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:613:9 | LL | _x if false => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error: aborting due to 49 previous errors diff --git a/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr b/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr index 9b57c895eea32..2e5511527d59c 100644 --- a/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr +++ b/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr @@ -4,6 +4,7 @@ error: unreachable pattern LL | _ => {} | ^ | + = note: this pattern matches no values because `!` is uninhabited note: the lint level is defined here --> $DIR/empty-types.rs:17:9 | @@ -15,6 +16,8 @@ error: unreachable pattern | LL | _x => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: type `&!` is non-empty --> $DIR/empty-types.rs:58:11 @@ -36,24 +39,32 @@ error: unreachable pattern | LL | (_, _) => {} | ^^^^^^ + | + = note: this pattern matches no values because `(u32, !)` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:80:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `(!, !)` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:83:9 | LL | (_, _) => {} | ^^^^^^ + | + = note: this pattern matches no values because `(!, !)` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:87:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: `Ok(_)` not covered --> $DIR/empty-types.rs:91:11 @@ -79,12 +90,16 @@ error: unreachable pattern | LL | Err(_) => {} | ^^^^^^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:104:9 | LL | Err(_) => {} | ^^^^^^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered --> $DIR/empty-types.rs:101:11 @@ -137,60 +152,80 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:123:9 | LL | Ok(_) => {} | ^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:126:9 | LL | Ok(_) => {} | ^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:127:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:130:9 | LL | Ok(_) => {} | ^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:131:9 | LL | Err(_) => {} | ^^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:140:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:143:13 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:152:13 | LL | Some(_) => {} | ^^^^^^^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:156:13 | +LL | None => {} + | ---- matches all the values already LL | _ => {} - | ^ + | ^ unreachable pattern error[E0004]: non-exhaustive patterns: `Some(_)` not covered --> $DIR/empty-types.rs:165:15 @@ -216,54 +251,72 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:213:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:218:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:223:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:229:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:288:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:291:9 | LL | (_, _) => {} | ^^^^^^ + | + = note: this pattern matches no values because `(!, !)` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:294:9 | LL | Ok(_) => {} | ^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:295:9 | LL | Err(_) => {} | ^^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty --> $DIR/empty-types.rs:316:11 @@ -403,18 +456,24 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `[!; 3]` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:372:9 | LL | [_, _, _] => {} | ^^^^^^^^^ + | + = note: this pattern matches no values because `[!; 3]` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:375:9 | LL | [_, ..] => {} | ^^^^^^^ + | + = note: this pattern matches no values because `[!; 3]` is uninhabited error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty --> $DIR/empty-types.rs:389:11 @@ -433,8 +492,10 @@ LL + } error: unreachable pattern --> $DIR/empty-types.rs:396:9 | +LL | [] => {} + | -- matches all the values already LL | _ => {} - | ^ + | ^ unreachable pattern error[E0004]: non-exhaustive patterns: `[]` not covered --> $DIR/empty-types.rs:398:11 @@ -455,24 +516,34 @@ error: unreachable pattern | LL | Some(_) => {} | ^^^^^^^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:422:9 | LL | Some(_a) => {} | ^^^^^^^^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:427:9 | +LL | None => {} + | ---- matches all the values already +LL | // !useful, !reachable LL | _ => {} - | ^ + | ^ unreachable pattern error: unreachable pattern --> $DIR/empty-types.rs:432:9 | +LL | None => {} + | ---- matches all the values already +LL | // !useful, !reachable LL | _a => {} - | ^^ + | ^^ unreachable pattern error[E0004]: non-exhaustive patterns: `&Some(_)` not covered --> $DIR/empty-types.rs:452:11 @@ -569,24 +640,32 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:607:9 | LL | _x => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:610:9 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:613:9 | LL | _x if false => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: `&_` not covered --> $DIR/empty-types.rs:638:11 diff --git a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr index 0ff2472922e4a..4856a2f8e08d3 100644 --- a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr +++ b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr @@ -13,6 +13,7 @@ error: unreachable pattern LL | _ => {} | ^ | + = note: this pattern matches no values because `!` is uninhabited note: the lint level is defined here --> $DIR/empty-types.rs:17:9 | @@ -24,6 +25,8 @@ error: unreachable pattern | LL | _x => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: type `&!` is non-empty --> $DIR/empty-types.rs:58:11 @@ -73,6 +76,8 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(!)` not covered --> $DIR/empty-types.rs:91:11 @@ -218,12 +223,16 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:143:13 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `Void` is uninhabited error[E0004]: non-exhaustive patterns: `Some(!)` not covered --> $DIR/empty-types.rs:146:15 @@ -266,36 +275,48 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:213:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:218:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:223:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:229:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:288:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty --> $DIR/empty-types.rs:316:11 @@ -460,8 +481,10 @@ LL + } error: unreachable pattern --> $DIR/empty-types.rs:396:9 | +LL | [] => {} + | -- matches all the values already LL | _ => {} - | ^ + | ^ unreachable pattern error[E0004]: non-exhaustive patterns: `[]` not covered --> $DIR/empty-types.rs:398:11 @@ -568,24 +591,32 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:607:9 | LL | _x => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:610:9 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:613:9 | LL | _x if false => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: `&!` not covered --> $DIR/empty-types.rs:638:11 diff --git a/tests/ui/pattern/usefulness/empty-types.normal.stderr b/tests/ui/pattern/usefulness/empty-types.normal.stderr index 1d13802a2bdc7..78db9ee349b4f 100644 --- a/tests/ui/pattern/usefulness/empty-types.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-types.normal.stderr @@ -4,6 +4,7 @@ error: unreachable pattern LL | _ => {} | ^ | + = note: this pattern matches no values because `!` is uninhabited note: the lint level is defined here --> $DIR/empty-types.rs:17:9 | @@ -15,6 +16,8 @@ error: unreachable pattern | LL | _x => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: type `&!` is non-empty --> $DIR/empty-types.rs:58:11 @@ -64,6 +67,8 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered --> $DIR/empty-types.rs:91:11 @@ -209,12 +214,16 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:143:13 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `Void` is uninhabited error[E0004]: non-exhaustive patterns: `Some(_)` not covered --> $DIR/empty-types.rs:146:15 @@ -257,36 +266,48 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:213:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:218:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:223:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:229:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:288:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty --> $DIR/empty-types.rs:316:11 @@ -451,8 +472,10 @@ LL + } error: unreachable pattern --> $DIR/empty-types.rs:396:9 | +LL | [] => {} + | -- matches all the values already LL | _ => {} - | ^ + | ^ unreachable pattern error[E0004]: non-exhaustive patterns: `[]` not covered --> $DIR/empty-types.rs:398:11 @@ -559,24 +582,32 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:607:9 | LL | _x => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:610:9 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:613:9 | LL | _x if false => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: `&_` not covered --> $DIR/empty-types.rs:638:11 diff --git a/tests/ui/pattern/usefulness/explain-unreachable-pats.rs b/tests/ui/pattern/usefulness/explain-unreachable-pats.rs new file mode 100644 index 0000000000000..98f781b6a09f7 --- /dev/null +++ b/tests/ui/pattern/usefulness/explain-unreachable-pats.rs @@ -0,0 +1,101 @@ +#![feature(never_type)] +#![feature(min_exhaustive_patterns)] +#![deny(unreachable_patterns)] +//~^ NOTE lint level is defined here + +#[rustfmt::skip] +fn main() { + match (0u8,) { + (1 | 2,) => {} + //~^ NOTE matches all the values already + (2,) => {} + //~^ ERROR unreachable pattern + //~| NOTE unreachable pattern + _ => {} + } + + match (0u8,) { + (1,) => {} + //~^ NOTE matches some of the same values + (2,) => {} + //~^ NOTE matches some of the same values + (1 | 2,) => {} + //~^ ERROR unreachable pattern + //~| NOTE unreachable pattern + //~| NOTE these patterns collectively make the last one unreachable + //~| NOTE collectively making this unreachable + _ => {} + } + + let res: Result<(),!> = Ok(()); + match res { + Ok(_) => {} + Err(_) => {} + //~^ ERROR unreachable pattern + //~| NOTE this pattern matches no values because `!` is uninhabited + } + + #[derive(Copy, Clone)] + enum Void1 {} + #[derive(Copy, Clone)] + enum Void2 {} + // Only an empty type matched _by value_ can make an arm unreachable. We must get the right one. + let res1: Result<(), Void1> = Ok(()); + let res2: Result<(), Void2> = Ok(()); + match (&res1, res2) { + (Err(_), Err(_)) => {} + //~^ ERROR unreachable pattern + //~| NOTE this pattern matches no values because `Void2` is uninhabited + _ => {} + } + match (res1, &res2) { + (Err(_), Err(_)) => {} + //~^ ERROR unreachable pattern + //~| NOTE this pattern matches no values because `Void1` is uninhabited + _ => {} + } + + + if let (0 + //~^ NOTE matches all the values already + | 0, _) = (0, 0) {} + //~^ ERROR unreachable pattern + //~| NOTE unreachable pattern + + match (true, true) { + (_, true) if false => {} // Guarded patterns don't cover others + (true, _) => {} + //~^ NOTE matches some of the same values + (false, _) => {} + //~^ NOTE matches some of the same values + (_, true) => {} + //~^ ERROR unreachable pattern + //~| NOTE unreachable pattern + //~| NOTE these patterns collectively make the last one unreachable + //~| NOTE collectively making this unreachable + } + + match (true, true) { + (true, _) => {} + //~^ NOTE matches all the values already + (false, _) => {} + #[allow(unreachable_patterns)] + (_, true) => {} // Doesn't cover below because it's already unreachable. + (true, true) => {} + //~^ ERROR unreachable pattern + //~| NOTE unreachable pattern + } + + // Despite skipping some irrelevant cases, we still report a set of rows that covers the + // unreachable one. + match (true, true, 0) { + (true, _, _) => {} + (_, true, 0..10) => {} + //~^ NOTE matches all the values already + (_, true, 10..) => {} + (_, true, 3) => {} + //~^ ERROR unreachable pattern + //~| NOTE unreachable pattern + _ => {} + } +} diff --git a/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr b/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr new file mode 100644 index 0000000000000..e2eecf4a9f386 --- /dev/null +++ b/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr @@ -0,0 +1,104 @@ +error: unreachable pattern + --> $DIR/explain-unreachable-pats.rs:11:9 + | +LL | (1 | 2,) => {} + | -------- matches all the values already +LL | +LL | (2,) => {} + | ^^^^ unreachable pattern + | +note: the lint level is defined here + --> $DIR/explain-unreachable-pats.rs:3:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/explain-unreachable-pats.rs:22:9 + | +LL | (1 | 2,) => {} + | ^^^^^^^^ unreachable pattern + | +note: these patterns collectively make the last one unreachable + --> $DIR/explain-unreachable-pats.rs:22:9 + | +LL | (1,) => {} + | ---- matches some of the same values +LL | +LL | (2,) => {} + | ---- matches some of the same values +LL | +LL | (1 | 2,) => {} + | ^^^^^^^^ collectively making this unreachable + +error: unreachable pattern + --> $DIR/explain-unreachable-pats.rs:33:9 + | +LL | Err(_) => {} + | ^^^^^^ + | + = note: this pattern matches no values because `!` is uninhabited + +error: unreachable pattern + --> $DIR/explain-unreachable-pats.rs:46:9 + | +LL | (Err(_), Err(_)) => {} + | ^^^^^^^^^^^^^^^^ + | + = note: this pattern matches no values because `Void2` is uninhabited + +error: unreachable pattern + --> $DIR/explain-unreachable-pats.rs:52:9 + | +LL | (Err(_), Err(_)) => {} + | ^^^^^^^^^^^^^^^^ + | + = note: this pattern matches no values because `Void1` is uninhabited + +error: unreachable pattern + --> $DIR/explain-unreachable-pats.rs:61:11 + | +LL | if let (0 + | - matches all the values already +LL | +LL | | 0, _) = (0, 0) {} + | ^ unreachable pattern + +error: unreachable pattern + --> $DIR/explain-unreachable-pats.rs:71:9 + | +LL | (_, true) => {} + | ^^^^^^^^^ unreachable pattern + | +note: these patterns collectively make the last one unreachable + --> $DIR/explain-unreachable-pats.rs:71:9 + | +LL | (true, _) => {} + | --------- matches some of the same values +LL | +LL | (false, _) => {} + | ---------- matches some of the same values +LL | +LL | (_, true) => {} + | ^^^^^^^^^ collectively making this unreachable + +error: unreachable pattern + --> $DIR/explain-unreachable-pats.rs:84:9 + | +LL | (true, _) => {} + | --------- matches all the values already +... +LL | (true, true) => {} + | ^^^^^^^^^^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/explain-unreachable-pats.rs:96:9 + | +LL | (_, true, 0..10) => {} + | ---------------- matches all the values already +... +LL | (_, true, 3) => {} + | ^^^^^^^^^^^^ unreachable pattern + +error: aborting due to 9 previous errors + diff --git a/tests/ui/pattern/usefulness/floats.stderr b/tests/ui/pattern/usefulness/floats.stderr index 684f6c93a16c0..d0a8841d6a83a 100644 --- a/tests/ui/pattern/usefulness/floats.stderr +++ b/tests/ui/pattern/usefulness/floats.stderr @@ -14,8 +14,10 @@ LL + _ => todo!() error: unreachable pattern --> $DIR/floats.rs:18:9 | +LL | 0.01f16..=6.5f16 => {} + | ---------------- matches all the values already LL | 0.01f16 => {} - | ^^^^^^^ + | ^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/floats.rs:1:9 @@ -26,80 +28,118 @@ LL | #![deny(unreachable_patterns)] error: unreachable pattern --> $DIR/floats.rs:19:9 | +LL | 0.01f16..=6.5f16 => {} + | ---------------- matches all the values already +LL | 0.01f16 => {} LL | 0.02f16 => {} - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:20:9 | +LL | 0.01f16..=6.5f16 => {} + | ---------------- matches all the values already +... LL | 6.5f16 => {} - | ^^^^^^ + | ^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:31:9 | +LL | 0.01f32..=6.5f32 => {} + | ---------------- matches all the values already LL | 0.01f32 => {} - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:32:9 | +LL | 0.01f32..=6.5f32 => {} + | ---------------- matches all the values already +LL | 0.01f32 => {} LL | 0.02f32 => {} - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:33:9 | +LL | 0.01f32..=6.5f32 => {} + | ---------------- matches all the values already +... LL | 6.5f32 => {} - | ^^^^^^ + | ^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:45:9 | +LL | 0.01f64..=6.5f64 => {} + | ---------------- matches all the values already +LL | 0.005f64 => {} LL | 0.01f64 => {} - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:46:9 | +LL | 0.01f64..=6.5f64 => {} + | ---------------- matches all the values already +... LL | 0.02f64 => {} - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:47:9 | +LL | 0.01f64..=6.5f64 => {} + | ---------------- matches all the values already +... LL | 6.5f64 => {} - | ^^^^^^ + | ^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:49:9 | +LL | 0.01f64..=6.5f64 => {} + | ---------------- matches all the values already +... LL | 1.0f64..=4.0f64 => {} - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:62:9 | +LL | 0.01f128..=6.5f128 => {} + | ------------------ matches all the values already +LL | 0.005f128 => {} LL | 0.01f128 => {} - | ^^^^^^^^ + | ^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:63:9 | +LL | 0.01f128..=6.5f128 => {} + | ------------------ matches all the values already +... LL | 0.02f128 => {} - | ^^^^^^^^ + | ^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:64:9 | +LL | 0.01f128..=6.5f128 => {} + | ------------------ matches all the values already +... LL | 6.5f128 => {} - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:66:9 | +LL | 0.01f128..=6.5f128 => {} + | ------------------ matches all the values already +... LL | 1.0f128..=4.0f128 => {} - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ unreachable pattern error: aborting due to 15 previous errors diff --git a/tests/ui/pattern/usefulness/impl-trait.stderr b/tests/ui/pattern/usefulness/impl-trait.stderr index ba8b12f9f66c6..c079f5a259dde 100644 --- a/tests/ui/pattern/usefulness/impl-trait.stderr +++ b/tests/ui/pattern/usefulness/impl-trait.stderr @@ -4,6 +4,7 @@ error: unreachable pattern LL | _ => {} | ^ | + = note: this pattern matches no values because `Void` is uninhabited note: the lint level is defined here --> $DIR/impl-trait.rs:5:9 | @@ -15,36 +16,48 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/impl-trait.rs:45:13 | LL | Some(_) => {} | ^^^^^^^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/impl-trait.rs:49:13 | +LL | None => {} + | ---- matches all the values already LL | _ => {} - | ^ + | ^ unreachable pattern error: unreachable pattern --> $DIR/impl-trait.rs:59:13 | LL | Some(_) => {} | ^^^^^^^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/impl-trait.rs:63:13 | +LL | None => {} + | ---- matches all the values already LL | _ => {} - | ^ + | ^ unreachable pattern error: unreachable pattern --> $DIR/impl-trait.rs:76:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/impl-trait.rs:86:9 @@ -59,12 +72,16 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/impl-trait.rs:105:9 | +LL | Some((a, b)) => {} + | ------------ matches all the values already LL | Some((mut x, mut y)) => { - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/impl-trait.rs:124:13 @@ -79,12 +96,16 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `SecretelyVoid` is uninhabited error: unreachable pattern --> $DIR/impl-trait.rs:151:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `SecretelyDoubleVoid` is uninhabited error[E0004]: non-exhaustive patterns: type `impl Copy` is non-empty --> $DIR/impl-trait.rs:23:11 diff --git a/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr b/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr index c5b028d2038c3..5d86007a853ec 100644 --- a/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr +++ b/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr @@ -2,7 +2,9 @@ error: unreachable pattern --> $DIR/reachability.rs:18:17 | LL | m!(0u8, 42, 42); - | ^^ + | -- ^^ unreachable pattern + | | + | matches all the values already | note: the lint level is defined here --> $DIR/reachability.rs:3:9 @@ -14,121 +16,211 @@ error: unreachable pattern --> $DIR/reachability.rs:22:22 | LL | m!(0u8, 20..=30, 20); - | ^^ + | ------- ^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:23:22 | LL | m!(0u8, 20..=30, 21); - | ^^ + | ------- ^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:24:22 | LL | m!(0u8, 20..=30, 25); - | ^^ + | ------- ^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:25:22 | LL | m!(0u8, 20..=30, 29); - | ^^ + | ------- ^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:26:22 | LL | m!(0u8, 20..=30, 30); - | ^^ + | ------- ^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:29:21 | LL | m!(0u8, 20..30, 20); - | ^^ + | ------ ^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:30:21 | LL | m!(0u8, 20..30, 21); - | ^^ + | ------ ^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:31:21 | LL | m!(0u8, 20..30, 25); - | ^^ + | ------ ^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:32:21 | LL | m!(0u8, 20..30, 29); - | ^^ + | ------ ^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:36:22 | LL | m!(0u8, 20..=30, 20..=30); - | ^^^^^^^ + | ------- ^^^^^^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:37:22 | LL | m!(0u8, 20.. 30, 20.. 30); - | ^^^^^^^ + | ------- ^^^^^^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:38:22 | LL | m!(0u8, 20..=30, 20.. 30); - | ^^^^^^^ + | ------- ^^^^^^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:40:22 | LL | m!(0u8, 20..=30, 21..=30); - | ^^^^^^^ + | ------- ^^^^^^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:41:22 | LL | m!(0u8, 20..=30, 20..=29); - | ^^^^^^^ + | ------- ^^^^^^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:43:24 | LL | m!('a', 'A'..='z', 'a'..='z'); - | ^^^^^^^^^ + | --------- ^^^^^^^^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:50:9 | LL | 5..=8 => {}, - | ^^^^^ + | ^^^^^ unreachable pattern + | +note: these patterns collectively make the last one unreachable + --> $DIR/reachability.rs:50:9 + | +LL | 5 => {}, + | - matches some of the same values +LL | 6 => {}, + | - matches some of the same values +LL | 7 => {}, + | - matches some of the same values +LL | 8 => {}, + | - matches some of the same values +LL | 5..=8 => {}, + | ^^^^^ collectively making this unreachable error: unreachable pattern --> $DIR/reachability.rs:56:9 | LL | 5..15 => {}, - | ^^^^^ + | ^^^^^ unreachable pattern + | +note: these patterns collectively make the last one unreachable + --> $DIR/reachability.rs:56:9 + | +LL | 0..10 => {}, + | ----- matches some of the same values +LL | 10..20 => {}, + | ------ matches some of the same values +LL | 5..15 => {}, + | ^^^^^ collectively making this unreachable error: unreachable pattern --> $DIR/reachability.rs:63:9 | LL | 5..25 => {}, - | ^^^^^ + | ^^^^^ unreachable pattern + | +note: these patterns collectively make the last one unreachable + --> $DIR/reachability.rs:63:9 + | +LL | 0..10 => {}, + | ----- matches some of the same values +LL | 10..20 => {}, + | ------ matches some of the same values +LL | 20..30 => {}, + | ------ matches some of the same values +LL | 5..25 => {}, + | ^^^^^ collectively making this unreachable error: unreachable pattern --> $DIR/reachability.rs:71:9 | LL | 5..25 => {}, - | ^^^^^ + | ^^^^^ unreachable pattern + | +note: these patterns collectively make the last one unreachable + --> $DIR/reachability.rs:71:9 + | +LL | 0..10 => {}, + | ----- matches some of the same values +LL | 10 => {}, + | -- matches some of the same values +LL | 11..=23 => {}, + | ------- matches some of the same values +LL | 19..30 => {}, + | ------ matches some of the same values +LL | 5..25 => {}, + | ^^^^^ collectively making this unreachable error: unreachable pattern --> $DIR/reachability.rs:77:9 | LL | 5..15 => {}, - | ^^^^^ + | ^^^^^ unreachable pattern + | +note: these patterns collectively make the last one unreachable + --> $DIR/reachability.rs:77:9 + | +LL | 0..10 => {}, + | ----- matches some of the same values +LL | 10..20 => {}, + | ------ matches some of the same values +LL | 5..15 => {}, + | ^^^^^ collectively making this unreachable error: unreachable pattern --> $DIR/reachability.rs:84:9 @@ -142,19 +234,34 @@ error: unreachable pattern --> $DIR/reachability.rs:89:9 | LL | '\u{D7FF}'..='\u{E000}' => {}, - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern + | +note: these patterns collectively make the last one unreachable + --> $DIR/reachability.rs:89:9 + | +LL | '\u{0}'..='\u{D7FF}' => {}, + | -------------------- matches some of the same values +LL | '\u{E000}'..='\u{10_FFFF}' => {}, + | -------------------------- matches some of the same values +LL | '\u{D7FF}'..='\u{E000}' => {}, + | ^^^^^^^^^^^^^^^^^^^^^^^ collectively making this unreachable error: unreachable pattern --> $DIR/reachability.rs:105:9 | +LL | &42 => {} + | --- matches all the values already LL | &FOO => {} - | ^^^^ + | ^^^^ unreachable pattern error: unreachable pattern --> $DIR/reachability.rs:106:9 | +LL | &42 => {} + | --- matches all the values already +LL | &FOO => {} LL | BAR => {} - | ^^^ + | ^^^ unreachable pattern error: aborting due to 25 previous errors diff --git a/tests/ui/pattern/usefulness/issue-12116.stderr b/tests/ui/pattern/usefulness/issue-12116.stderr index 199bdc6ac978c..b2c2be97563c7 100644 --- a/tests/ui/pattern/usefulness/issue-12116.stderr +++ b/tests/ui/pattern/usefulness/issue-12116.stderr @@ -1,8 +1,10 @@ error: unreachable pattern --> $DIR/issue-12116.rs:15:9 | +LL | &IntList::Cons(val, box ref next_list) => tail(next_list), + | -------------------------------------- matches all the values already LL | &IntList::Cons(val, box IntList::Nil) => IntList::Cons(val, Box::new(IntList::Nil)), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/issue-12116.rs:4:9 diff --git a/tests/ui/pattern/usefulness/issue-12369.stderr b/tests/ui/pattern/usefulness/issue-12369.stderr index 2b6e2e14b7ca8..7754cbc24843f 100644 --- a/tests/ui/pattern/usefulness/issue-12369.stderr +++ b/tests/ui/pattern/usefulness/issue-12369.stderr @@ -2,8 +2,17 @@ error: unreachable pattern --> $DIR/issue-12369.rs:9:9 | LL | &[10,a, ref rest @ ..] => 10 - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern | +note: these patterns collectively make the last one unreachable + --> $DIR/issue-12369.rs:9:9 + | +LL | &[a,b,c] => 3, + | -------- matches some of the same values +LL | &[a, ref rest @ ..] => a, + | ------------------- matches some of the same values +LL | &[10,a, ref rest @ ..] => 10 + | ^^^^^^^^^^^^^^^^^^^^^^ collectively making this unreachable note: the lint level is defined here --> $DIR/issue-12369.rs:1:9 | diff --git a/tests/ui/pattern/usefulness/issue-13727.stderr b/tests/ui/pattern/usefulness/issue-13727.stderr index ab80c56ea88a0..ca8533b33a467 100644 --- a/tests/ui/pattern/usefulness/issue-13727.stderr +++ b/tests/ui/pattern/usefulness/issue-13727.stderr @@ -1,8 +1,10 @@ error: unreachable pattern --> $DIR/issue-13727.rs:7:5 | +LL | 256 => print!("0b1110\n"), + | --- matches all the values already LL | 512 => print!("0b1111\n"), - | ^^^ + | ^^^ unreachable pattern | note: the lint level is defined here --> $DIR/issue-13727.rs:2:9 diff --git a/tests/ui/pattern/usefulness/issue-30240-b.stderr b/tests/ui/pattern/usefulness/issue-30240-b.stderr index 74d39eba98c9d..749515fc94b65 100644 --- a/tests/ui/pattern/usefulness/issue-30240-b.stderr +++ b/tests/ui/pattern/usefulness/issue-30240-b.stderr @@ -2,7 +2,9 @@ error: unreachable pattern --> $DIR/issue-30240-b.rs:12:9 | LL | "hello" => {} - | ^^^^^^^ + | ------- matches all the values already +LL | "hello" => {} + | ^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/issue-30240-b.rs:1:9 diff --git a/tests/ui/pattern/usefulness/issue-31221.stderr b/tests/ui/pattern/usefulness/issue-31221.stderr index 7d34914445637..596f4d8096d9a 100644 --- a/tests/ui/pattern/usefulness/issue-31221.stderr +++ b/tests/ui/pattern/usefulness/issue-31221.stderr @@ -23,10 +23,18 @@ LL | &Var2 => (), error: unreachable pattern --> $DIR/issue-31221.rs:31:9 | -LL | (c, d) => (), - | ------ matches any value LL | anything => () | ^^^^^^^^ unreachable pattern + | +note: these patterns collectively make the last one unreachable + --> $DIR/issue-31221.rs:31:9 + | +LL | (Var1, b) => (), + | --------- matches some of the same values +LL | (c, d) => (), + | ------ matches some of the same values +LL | anything => () + | ^^^^^^^^ collectively making this unreachable error: aborting due to 3 previous errors diff --git a/tests/ui/pattern/usefulness/issue-57472.stderr b/tests/ui/pattern/usefulness/issue-57472.stderr index c814eaec0d19e..68b5b7cb7911a 100644 --- a/tests/ui/pattern/usefulness/issue-57472.stderr +++ b/tests/ui/pattern/usefulness/issue-57472.stderr @@ -1,8 +1,10 @@ error: unreachable pattern --> $DIR/issue-57472.rs:15:13 | +LL | Punned { foo: [_], .. } => println!("foo"), + | ----------------------- matches all the values already LL | Punned { bar: [_], .. } => println!("bar"), - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/issue-57472.rs:2:9 @@ -13,8 +15,10 @@ LL | #![deny(unreachable_patterns)] error: unreachable pattern --> $DIR/issue-57472.rs:32:17 | +LL | Punned { foo: [_] } => println!("foo"), + | ------------------- matches all the values already LL | Punned { bar: [_] } => println!("bar"), - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ unreachable pattern error: aborting due to 2 previous errors diff --git a/tests/ui/pattern/usefulness/match-arm-statics.stderr b/tests/ui/pattern/usefulness/match-arm-statics.stderr index a5dffebf69967..b6f2b47047dce 100644 --- a/tests/ui/pattern/usefulness/match-arm-statics.stderr +++ b/tests/ui/pattern/usefulness/match-arm-statics.stderr @@ -1,8 +1,11 @@ error: unreachable pattern --> $DIR/match-arm-statics.rs:25:9 | +LL | TRUE_TRUE => (), + | --------- matches all the values already +... LL | (true, true) => () - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/match-arm-statics.rs:2:9 @@ -13,14 +16,29 @@ LL | #![deny(unreachable_patterns)] error: unreachable pattern --> $DIR/match-arm-statics.rs:40:9 | +LL | Some(Some(EAST)) => (), + | ---------------- matches all the values already +... LL | Some(Some(East)) => (), - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/match-arm-statics.rs:60:9 | LL | Foo { bar: Some(EAST), baz: NewBool(false) } => () - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern + | +note: these patterns collectively make the last one unreachable + --> $DIR/match-arm-statics.rs:60:9 + | +LL | Foo { bar: _, baz: NEW_FALSE } => (), + | ------------------------------ matches some of the same values +... +LL | Foo { bar: Some(EAST), .. } => (), + | --------------------------- matches some of the same values +LL | Foo { bar: Some(North), baz: NewBool(true) } => (), +LL | Foo { bar: Some(EAST), baz: NewBool(false) } => () + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ collectively making this unreachable error: aborting due to 3 previous errors diff --git a/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr b/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr index 0c582be8df8bc..39675e2bdd4bb 100644 --- a/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr +++ b/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr @@ -1,8 +1,10 @@ error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:8:9 | +LL | b"AAAA" => {}, + | ------- matches all the values already LL | &[0x41, 0x41, 0x41, 0x41] => {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/match-byte-array-patterns.rs:1:9 @@ -13,44 +15,58 @@ LL | #![deny(unreachable_patterns)] error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:14:9 | +LL | &[0x41, 0x41, 0x41, 0x41] => {} + | ------------------------- matches all the values already LL | b"AAAA" => {}, - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:20:9 | +LL | &[_, 0x41, 0x41, 0x41] => {}, + | ---------------------- matches all the values already LL | b"AAAA" => {}, - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:26:9 | +LL | &[0x41, .., 0x41] => {} + | ----------------- matches all the values already LL | b"AAAA" => {}, - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:34:9 | +LL | b"AAAA" => {}, + | ------- matches all the values already LL | &[0x41, 0x41, 0x41, 0x41] => {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:40:9 | +LL | &[0x41, 0x41, 0x41, 0x41] => {} + | ------------------------- matches all the values already LL | b"AAAA" => {}, - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:46:9 | +LL | &[_, 0x41, 0x41, 0x41] => {}, + | ---------------------- matches all the values already LL | b"AAAA" => {}, - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:52:9 | +LL | &[0x41, .., 0x41] => {} + | ----------------- matches all the values already LL | b"AAAA" => {}, - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: aborting due to 8 previous errors diff --git a/tests/ui/pattern/usefulness/match-ref-ice.stderr b/tests/ui/pattern/usefulness/match-ref-ice.stderr index 0dbfa776f6959..9c5af47cc1eb5 100644 --- a/tests/ui/pattern/usefulness/match-ref-ice.stderr +++ b/tests/ui/pattern/usefulness/match-ref-ice.stderr @@ -1,8 +1,10 @@ error: unreachable pattern --> $DIR/match-ref-ice.rs:13:9 | +LL | [1, ref _madoka, 3] => (), + | ------------------- matches all the values already LL | [1, 2, 3] => (), - | ^^^^^^^^^ + | ^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/match-ref-ice.rs:1:9 diff --git a/tests/ui/pattern/usefulness/match-vec-fixed.stderr b/tests/ui/pattern/usefulness/match-vec-fixed.stderr index e388a06cb9a14..04507a228564d 100644 --- a/tests/ui/pattern/usefulness/match-vec-fixed.stderr +++ b/tests/ui/pattern/usefulness/match-vec-fixed.stderr @@ -2,7 +2,9 @@ error: unreachable pattern --> $DIR/match-vec-fixed.rs:7:9 | LL | [_, _, _] => {} - | ^^^^^^^^^ + | --------- matches all the values already +LL | [_, _, _] => {} + | ^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/match-vec-fixed.rs:1:9 @@ -14,7 +16,9 @@ error: unreachable pattern --> $DIR/match-vec-fixed.rs:11:9 | LL | [_, 1, _] => {} - | ^^^^^^^^^ + | --------- matches all the values already +LL | [_, 1, _] => {} + | ^^^^^^^^^ unreachable pattern error: aborting due to 2 previous errors diff --git a/tests/ui/pattern/usefulness/match-vec-unreachable.stderr b/tests/ui/pattern/usefulness/match-vec-unreachable.stderr index 672fd92fb5ebd..865f5b319a775 100644 --- a/tests/ui/pattern/usefulness/match-vec-unreachable.stderr +++ b/tests/ui/pattern/usefulness/match-vec-unreachable.stderr @@ -1,8 +1,10 @@ error: unreachable pattern --> $DIR/match-vec-unreachable.rs:8:9 | +LL | [a, (2, 3), _] => (), + | -------------- matches all the values already LL | [(1, 2), (2, 3), b] => (), - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/match-vec-unreachable.rs:1:9 @@ -13,14 +15,18 @@ LL | #![deny(unreachable_patterns)] error: unreachable pattern --> $DIR/match-vec-unreachable.rs:18:9 | +LL | [ref a, _, _, ..] => { println!("{}", a); } + | ----------------- matches all the values already LL | [_, _, _, _, _] => { } - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/match-vec-unreachable.rs:26:9 | +LL | ['a', 'b', 'c', ref _tail @ ..] => {} + | ------------------------------- matches all the values already LL | ['a', 'b', 'c'] => {} - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ unreachable pattern error: aborting due to 3 previous errors diff --git a/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr b/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr index dcad11a38a7eb..12db48590a4d9 100644 --- a/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr +++ b/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr @@ -1,8 +1,11 @@ error: unreachable pattern --> $DIR/slice-pattern-const-2.rs:9:9 | +LL | MAGIC_TEST => (), + | ---------- matches all the values already +LL | [0x00, 0x00, 0x00, 0x00] => (), LL | [4, 5, 6, 7] => (), - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/slice-pattern-const-2.rs:1:9 @@ -13,20 +16,26 @@ LL | #![deny(unreachable_patterns)] error: unreachable pattern --> $DIR/slice-pattern-const-2.rs:15:9 | +LL | MAGIC_TEST => (), + | ---------- matches all the values already LL | [4, 5, 6, 7] => (), - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-pattern-const-2.rs:21:9 | +LL | [4, 5, 6, 7] => (), + | ------------ matches all the values already LL | MAGIC_TEST => (), - | ^^^^^^^^^^ + | ^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-pattern-const-2.rs:28:9 | +LL | [4] => (), + | --- matches all the values already LL | FOO => (), - | ^^^ + | ^^^ unreachable pattern error: aborting due to 4 previous errors diff --git a/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr b/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr index b90b3a88a1860..5a66799d9c97b 100644 --- a/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr +++ b/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr @@ -1,8 +1,11 @@ error: unreachable pattern --> $DIR/slice-pattern-const-3.rs:9:9 | +LL | MAGIC_TEST => (), + | ---------- matches all the values already +LL | ["0x00", "0x00", "0x00", "0x00"] => (), LL | ["4", "5", "6", "7"] => (), - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/slice-pattern-const-3.rs:1:9 @@ -13,20 +16,26 @@ LL | #![deny(unreachable_patterns)] error: unreachable pattern --> $DIR/slice-pattern-const-3.rs:15:9 | +LL | MAGIC_TEST => (), + | ---------- matches all the values already LL | ["4", "5", "6", "7"] => (), - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-pattern-const-3.rs:21:9 | +LL | ["4", "5", "6", "7"] => (), + | -------------------- matches all the values already LL | MAGIC_TEST => (), - | ^^^^^^^^^^ + | ^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-pattern-const-3.rs:28:9 | +LL | ["boo"] => (), + | ------- matches all the values already LL | FOO => (), - | ^^^ + | ^^^ unreachable pattern error: aborting due to 4 previous errors diff --git a/tests/ui/pattern/usefulness/slice-pattern-const.stderr b/tests/ui/pattern/usefulness/slice-pattern-const.stderr index 1fffb9fedbf2e..87a85acc4c535 100644 --- a/tests/ui/pattern/usefulness/slice-pattern-const.stderr +++ b/tests/ui/pattern/usefulness/slice-pattern-const.stderr @@ -1,8 +1,11 @@ error: unreachable pattern --> $DIR/slice-pattern-const.rs:9:9 | +LL | MAGIC_TEST => (), + | ---------- matches all the values already +LL | [0x00, 0x00, 0x00, 0x00] => (), LL | [84, 69, 83, 84] => (), - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/slice-pattern-const.rs:1:9 @@ -13,50 +16,68 @@ LL | #![deny(unreachable_patterns)] error: unreachable pattern --> $DIR/slice-pattern-const.rs:15:9 | +LL | MAGIC_TEST => (), + | ---------- matches all the values already LL | [84, 69, 83, 84] => (), - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-pattern-const.rs:21:9 | +LL | [84, 69, 83, 84] => (), + | ---------------- matches all the values already LL | MAGIC_TEST => (), - | ^^^^^^^^^^ + | ^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-pattern-const.rs:28:9 | +LL | [4] => (), + | --- matches all the values already LL | FOO => (), - | ^^^ + | ^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-pattern-const.rs:35:9 | +LL | [4] => (), + | --- matches all the values already LL | BAR => (), - | ^^^ + | ^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-pattern-const.rs:43:9 | +LL | [] => (), + | -- matches all the values already LL | BOO => (), - | ^^^ + | ^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-pattern-const.rs:44:9 | +LL | [] => (), + | -- matches all the values already +LL | BOO => (), LL | b"" => (), - | ^^^ + | ^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-pattern-const.rs:45:9 | +LL | [] => (), + | -- matches all the values already +... LL | _ => (), - | ^ + | ^ unreachable pattern error: unreachable pattern --> $DIR/slice-pattern-const.rs:51:9 | +LL | CONST1 => {} + | ------ matches all the values already LL | [true] => {} - | ^^^^^^ + | ^^^^^^ unreachable pattern error: aborting due to 9 previous errors diff --git a/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr b/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr index 607ffb76595e9..40fbb00de1f2c 100644 --- a/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr +++ b/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr @@ -2,7 +2,9 @@ error: unreachable pattern --> $DIR/slice-patterns-reachability.rs:8:9 | LL | [true, ..] => {} - | ^^^^^^^^^^ + | ---------- matches all the values already +LL | [true, ..] => {} + | ^^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/slice-patterns-reachability.rs:1:9 @@ -13,32 +15,45 @@ LL | #![deny(unreachable_patterns)] error: unreachable pattern --> $DIR/slice-patterns-reachability.rs:9:9 | +LL | [true, ..] => {} + | ---------- matches all the values already +LL | [true, ..] => {} LL | [true] => {} - | ^^^^^^ + | ^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-patterns-reachability.rs:14:9 | LL | [.., true] => {} - | ^^^^^^^^^^ + | ---------- matches all the values already +LL | [.., true] => {} + | ^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-patterns-reachability.rs:15:9 | +LL | [.., true] => {} + | ---------- matches all the values already +LL | [.., true] => {} LL | [true] => {} - | ^^^^^^ + | ^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-patterns-reachability.rs:20:9 | LL | [false, .., true] => {} - | ^^^^^^^^^^^^^^^^^ + | ----------------- matches all the values already +LL | [false, .., true] => {} + | ^^^^^^^^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-patterns-reachability.rs:21:9 | +LL | [false, .., true] => {} + | ----------------- matches all the values already +LL | [false, .., true] => {} LL | [false, true] => {} - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ unreachable pattern error: aborting due to 6 previous errors diff --git a/tests/ui/pattern/usefulness/top-level-alternation.stderr b/tests/ui/pattern/usefulness/top-level-alternation.stderr index 17fa951c53905..ad846f2315597 100644 --- a/tests/ui/pattern/usefulness/top-level-alternation.stderr +++ b/tests/ui/pattern/usefulness/top-level-alternation.stderr @@ -2,7 +2,9 @@ error: unreachable pattern --> $DIR/top-level-alternation.rs:4:23 | LL | while let 0..=2 | 1 = 0 {} - | ^ + | ----- ^ unreachable pattern + | | + | matches all the values already | note: the lint level is defined here --> $DIR/top-level-alternation.rs:1:9 @@ -14,61 +16,90 @@ error: unreachable pattern --> $DIR/top-level-alternation.rs:5:20 | LL | if let 0..=2 | 1 = 0 {} - | ^ + | ----- ^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/top-level-alternation.rs:9:15 | +LL | 0 + | - matches all the values already LL | | 0 => {} - | ^ + | ^ unreachable pattern error: unreachable pattern --> $DIR/top-level-alternation.rs:14:15 | +LL | Some(0) + | ------- matches all the values already LL | | Some(0) => {} - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/top-level-alternation.rs:19:9 | +LL | (0, _) | (_, 0) => {} + | --------------- matches all the values already LL | (0, 0) => {} - | ^^^^^^ + | ^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/top-level-alternation.rs:39:9 | +LL | None | Some(_) => {} + | -------------- matches all the values already LL | _ => {} - | ^ + | ^ unreachable pattern error: unreachable pattern --> $DIR/top-level-alternation.rs:43:9 | +LL | None | Some(_) => {} + | -------------- matches all the values already LL | Some(_) => {} - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/top-level-alternation.rs:44:9 | +LL | None | Some(_) => {} + | -------------- matches all the values already +LL | Some(_) => {} LL | None => {} - | ^^^^ + | ^^^^ unreachable pattern error: unreachable pattern --> $DIR/top-level-alternation.rs:49:9 | LL | None | Some(_) => {} - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ unreachable pattern + | +note: these patterns collectively make the last one unreachable + --> $DIR/top-level-alternation.rs:49:9 + | +LL | Some(_) => {} + | ------- matches some of the same values +LL | None => {} + | ---- matches some of the same values +LL | None | Some(_) => {} + | ^^^^^^^^^^^^^^ collectively making this unreachable error: unreachable pattern --> $DIR/top-level-alternation.rs:53:9 | +LL | 1 | 2 => {}, + | ----- matches all the values already LL | 1..=2 => {}, - | ^^^^^ + | ^^^^^ unreachable pattern error: unreachable pattern --> $DIR/top-level-alternation.rs:56:14 | LL | let (0 | 0) = 0 else { return }; - | ^ + | - ^ unreachable pattern + | | + | matches all the values already error: aborting due to 11 previous errors diff --git a/tests/ui/reachable/unreachable-arm.stderr b/tests/ui/reachable/unreachable-arm.stderr index 60db8217640fd..796274040302b 100644 --- a/tests/ui/reachable/unreachable-arm.stderr +++ b/tests/ui/reachable/unreachable-arm.stderr @@ -1,8 +1,10 @@ error: unreachable pattern --> $DIR/unreachable-arm.rs:11:9 | +LL | Foo::B(_) | Foo::A(box _, 1) => { } + | ---------------------------- matches all the values already LL | Foo::A(_, 1) => { } - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/unreachable-arm.rs:4:9 diff --git a/tests/ui/reachable/unreachable-loop-patterns.stderr b/tests/ui/reachable/unreachable-loop-patterns.stderr index 1dea9d813f9b4..bdd9b5ee41151 100644 --- a/tests/ui/reachable/unreachable-loop-patterns.stderr +++ b/tests/ui/reachable/unreachable-loop-patterns.stderr @@ -4,6 +4,7 @@ error: unreachable pattern LL | for _ in unimplemented!() as Void {} | ^ | + = note: this pattern matches no values because `Void` is uninhabited note: the lint level is defined here --> $DIR/unreachable-loop-patterns.rs:5:9 | diff --git a/tests/ui/reachable/unreachable-try-pattern.stderr b/tests/ui/reachable/unreachable-try-pattern.stderr index 8f3e23119fb9e..bc1a6fffda648 100644 --- a/tests/ui/reachable/unreachable-try-pattern.stderr +++ b/tests/ui/reachable/unreachable-try-pattern.stderr @@ -19,6 +19,7 @@ warning: unreachable pattern LL | let y = (match x { Ok(n) => Ok(n as u32), Err(e) => Err(e) })?; | ^^^^^ | + = note: this pattern matches no values because `!` is uninhabited note: the lint level is defined here --> $DIR/unreachable-try-pattern.rs:4:9 | @@ -30,6 +31,8 @@ warning: unreachable pattern | LL | let y = (match x { Ok(n) => Ok(n), Err(e) => Err(e) })?; | ^^^^^^ + | + = note: this pattern matches no values because `Void` is uninhabited warning: 3 warnings emitted diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.exh_pats.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.exh_pats.stderr index fe2a72d2a3180..a875041d89c57 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.exh_pats.stderr +++ b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.exh_pats.stderr @@ -4,6 +4,7 @@ error: unreachable pattern LL | Err(!), | ^^^^^^ | + = note: this pattern matches no values because `Void` is uninhabited note: the lint level is defined here --> $DIR/unreachable.rs:7:9 | @@ -15,30 +16,40 @@ error: unreachable pattern | LL | let (Ok(_x) | Err(!)) = res_void; | ^^^^^^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/unreachable.rs:22:12 | LL | if let Err(!) = res_void {} | ^^^^^^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/unreachable.rs:24:24 | LL | if let (Ok(true) | Err(!)) = res_void {} | ^^^^^^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/unreachable.rs:26:23 | LL | for (Ok(mut _x) | Err(!)) in [res_void] {} | ^^^^^^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/unreachable.rs:30:18 | LL | fn foo((Ok(_x) | Err(!)): Result) {} | ^^^^^^ + | + = note: this pattern matches no values because `Void` is uninhabited error: aborting due to 6 previous errors diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr index 7386f10a6fb2c..d5f58e436c5d8 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr @@ -4,6 +4,7 @@ error: unreachable pattern LL | _ => {} | ^ | + = note: this pattern matches no values because `EmptyNonExhaustiveEnum` is uninhabited note: the lint level is defined here --> $DIR/enum_same_crate_empty_match.rs:1:9 | diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr index 3034a67dc43b3..4ec4ec9705a8b 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr @@ -2,7 +2,9 @@ error: unreachable pattern --> $DIR/issue-65157-repeated-match-arm.rs:15:9 | LL | PartiallyInhabitedVariants::Struct { .. } => {}, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----------------------------------------- matches all the values already +LL | PartiallyInhabitedVariants::Struct { .. } => {}, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/issue-65157-repeated-match-arm.rs:2:9 diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr index 8bfd6e91f4dec..d5192a70ed550 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr @@ -4,6 +4,7 @@ error: unreachable pattern LL | Some(_x) => (), | ^^^^^^^^ | + = note: this pattern matches no values because `UninhabitedEnum` is uninhabited note: the lint level is defined here --> $DIR/patterns_same_crate.rs:1:9 | @@ -15,24 +16,32 @@ error: unreachable pattern | LL | Some(_x) => (), | ^^^^^^^^ + | + = note: this pattern matches no values because `UninhabitedVariants` is uninhabited error: unreachable pattern --> $DIR/patterns_same_crate.rs:61:15 | LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/patterns_same_crate.rs:65:15 | LL | while let Some(_x) = uninhabited_struct() { | ^^^^^^^^ + | + = note: this pattern matches no values because `UninhabitedStruct` is uninhabited error: unreachable pattern --> $DIR/patterns_same_crate.rs:68:15 | LL | while let Some(_x) = uninhabited_tuple_struct() { | ^^^^^^^^ + | + = note: this pattern matches no values because `UninhabitedTupleStruct` is uninhabited error: aborting due to 5 previous errors diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr index eed5dbb88deb0..8d0874fa9007e 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr @@ -16,7 +16,9 @@ error: unreachable pattern --> $DIR/warns.rs:15:25 | LL | x if let None | None = x => {} - | ^^^^ + | ---- ^^^^ unreachable pattern + | | + | matches all the values already | note: the lint level is defined here --> $DIR/warns.rs:12:8 diff --git a/tests/ui/uninhabited/uninhabited-patterns.stderr b/tests/ui/uninhabited/uninhabited-patterns.stderr index a6fda88f03281..ca62386d7ef02 100644 --- a/tests/ui/uninhabited/uninhabited-patterns.stderr +++ b/tests/ui/uninhabited/uninhabited-patterns.stderr @@ -4,6 +4,7 @@ error: unreachable pattern LL | Ok(box _) => (), | ^^^^^^^^^ | + = note: this pattern matches no values because `NotSoSecretlyEmpty` is uninhabited note: the lint level is defined here --> $DIR/uninhabited-patterns.rs:4:9 | @@ -15,12 +16,16 @@ error: unreachable pattern | LL | Err(Ok(_y)) => (), | ^^^^^^^^^^^ + | + = note: this pattern matches no values because `NotSoSecretlyEmpty` is uninhabited error: unreachable pattern --> $DIR/uninhabited-patterns.rs:42:15 | LL | while let Some(_y) = foo() { | ^^^^^^^^ + | + = note: this pattern matches no values because `NotSoSecretlyEmpty` is uninhabited error: aborting due to 3 previous errors