Auto merge of #117611 - Nadrieril:linear-pass-take-4, r=cjgillot
Rewrite exhaustiveness in one pass This is at least my 4th attempt at this in as many years x) Previous attempts were all too complicated or too slow. But we're finally here! The previous version of the exhaustiveness algorithm computed reachability for each arm then exhaustiveness of the whole match. Since each of these steps does roughly the same things, this rewrites the algorithm to do them all in one go. I also think this makes things much simpler. I also rewrote the documentation of the algorithm in depth. Hopefully it's up-to-date and easier to follow now. Plz comment if anything's unclear. r? `@oli-obk` I think you're one of the rare other people to understand the exhaustiveness algorithm? cc `@varkor` I know you're not active anymore, but if you feel like having a look you might enjoy this :D Fixes https://github.com/rust-lang/rust/issues/79307
This commit is contained in:
commit
ee80c8d0a8
@ -279,8 +279,10 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
|
|||||||
} else {
|
} else {
|
||||||
// Check the pattern for some things unrelated to exhaustiveness.
|
// Check the pattern for some things unrelated to exhaustiveness.
|
||||||
let refutable = if cx.refutable { Refutable } else { Irrefutable };
|
let refutable = if cx.refutable { Refutable } else { Irrefutable };
|
||||||
pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat));
|
pat.walk_always(|pat| {
|
||||||
pat.walk_always(|pat| check_for_bindings_named_same_as_variants(self, pat, refutable));
|
check_borrow_conflicts_in_at_patterns(self, pat);
|
||||||
|
check_for_bindings_named_same_as_variants(self, pat, refutable);
|
||||||
|
});
|
||||||
Ok(cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, pat)))
|
Ok(cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, pat)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -289,6 +291,7 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
|
|||||||
&self,
|
&self,
|
||||||
refutability: RefutableFlag,
|
refutability: RefutableFlag,
|
||||||
match_span: Option<Span>,
|
match_span: Option<Span>,
|
||||||
|
scrut_span: Span,
|
||||||
) -> MatchCheckCtxt<'p, 'tcx> {
|
) -> MatchCheckCtxt<'p, 'tcx> {
|
||||||
let refutable = match refutability {
|
let refutable = match refutability {
|
||||||
Irrefutable => false,
|
Irrefutable => false,
|
||||||
@ -299,7 +302,9 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
|
|||||||
param_env: self.param_env,
|
param_env: self.param_env,
|
||||||
module: self.tcx.parent_module(self.lint_level).to_def_id(),
|
module: self.tcx.parent_module(self.lint_level).to_def_id(),
|
||||||
pattern_arena: self.pattern_arena,
|
pattern_arena: self.pattern_arena,
|
||||||
|
match_lint_level: self.lint_level,
|
||||||
match_span,
|
match_span,
|
||||||
|
scrut_span,
|
||||||
refutable,
|
refutable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -330,7 +335,8 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
|
|||||||
source: hir::MatchSource,
|
source: hir::MatchSource,
|
||||||
expr_span: Span,
|
expr_span: Span,
|
||||||
) {
|
) {
|
||||||
let cx = self.new_cx(Refutable, Some(expr_span));
|
let scrut = &self.thir[scrut];
|
||||||
|
let cx = self.new_cx(Refutable, Some(expr_span), scrut.span);
|
||||||
|
|
||||||
let mut tarms = Vec::with_capacity(arms.len());
|
let mut tarms = Vec::with_capacity(arms.len());
|
||||||
for &arm in arms {
|
for &arm in arms {
|
||||||
@ -346,9 +352,8 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let scrut = &self.thir[scrut];
|
|
||||||
let scrut_ty = scrut.ty;
|
let scrut_ty = scrut.ty;
|
||||||
let report = compute_match_usefulness(&cx, &tarms, self.lint_level, scrut_ty, scrut.span);
|
let report = compute_match_usefulness(&cx, &tarms, scrut_ty);
|
||||||
|
|
||||||
match source {
|
match source {
|
||||||
// Don't report arm reachability of desugared `match $iter.into_iter() { iter => .. }`
|
// Don't report arm reachability of desugared `match $iter.into_iter() { iter => .. }`
|
||||||
@ -453,10 +458,10 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
|
|||||||
pat: &Pat<'tcx>,
|
pat: &Pat<'tcx>,
|
||||||
refutability: RefutableFlag,
|
refutability: RefutableFlag,
|
||||||
) -> Result<(MatchCheckCtxt<'p, 'tcx>, UsefulnessReport<'p, 'tcx>), ErrorGuaranteed> {
|
) -> Result<(MatchCheckCtxt<'p, 'tcx>, UsefulnessReport<'p, 'tcx>), ErrorGuaranteed> {
|
||||||
let cx = self.new_cx(refutability, None);
|
let cx = self.new_cx(refutability, None, pat.span);
|
||||||
let pat = self.lower_pattern(&cx, pat)?;
|
let pat = self.lower_pattern(&cx, pat)?;
|
||||||
let arms = [MatchArm { pat, hir_id: self.lint_level, has_guard: false }];
|
let arms = [MatchArm { pat, hir_id: self.lint_level, has_guard: false }];
|
||||||
let report = compute_match_usefulness(&cx, &arms, self.lint_level, pat.ty(), pat.span());
|
let report = compute_match_usefulness(&cx, &arms, pat.ty());
|
||||||
Ok((cx, report))
|
Ok((cx, report))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,46 +1,88 @@
|
|||||||
//! [`super::usefulness`] explains most of what is happening in this file. As explained there,
|
//! As explained in [`super::usefulness`], values and patterns are made from constructors applied to
|
||||||
//! values and patterns are made from constructors applied to fields. This file defines a
|
//! fields. This file defines a `Constructor` enum, a `Fields` struct, and various operations to
|
||||||
//! `Constructor` enum, a `Fields` struct, and various operations to manipulate them and convert
|
//! manipulate them and convert them from/to patterns.
|
||||||
//! them from/to patterns.
|
|
||||||
//!
|
//!
|
||||||
//! There's one idea that is not detailed in [`super::usefulness`] because the details are not
|
//! There are two important bits of core logic in this file: constructor inclusion and constructor
|
||||||
//! needed there: _constructor splitting_.
|
//! splitting. Constructor inclusion, i.e. whether a constructor is included in/covered by another,
|
||||||
|
//! is straightforward and defined in [`Constructor::is_covered_by`].
|
||||||
//!
|
//!
|
||||||
//! # Constructor splitting
|
//! Constructor splitting is mentioned in [`super::usefulness`] but not detailed. We describe it
|
||||||
|
//! precisely here.
|
||||||
//!
|
//!
|
||||||
//! The idea is as follows: given a constructor `c` and a matrix, we want to specialize in turn
|
|
||||||
//! with all the value constructors that are covered by `c`, and compute usefulness for each.
|
|
||||||
//! Instead of listing all those constructors (which is intractable), we group those value
|
|
||||||
//! constructors together as much as possible. Example:
|
|
||||||
//!
|
//!
|
||||||
|
//! # Constructor grouping and splitting
|
||||||
|
//!
|
||||||
|
//! As explained in the corresponding section in [`super::usefulness`], to make usefulness tractable
|
||||||
|
//! we need to group together constructors that have the same effect when they are used to
|
||||||
|
//! specialize the matrix.
|
||||||
|
//!
|
||||||
|
//! Example:
|
||||||
//! ```compile_fail,E0004
|
//! ```compile_fail,E0004
|
||||||
//! match (0, false) {
|
//! match (0, false) {
|
||||||
//! (0 ..=100, true) => {} // `p_1`
|
//! (0 ..=100, true) => {}
|
||||||
//! (50..=150, false) => {} // `p_2`
|
//! (50..=150, false) => {}
|
||||||
//! (0 ..=200, _) => {} // `q`
|
//! (0 ..=200, _) => {}
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! The naive approach would try all numbers in the range `0..=200`. But we can be a lot more
|
//! In this example we can restrict specialization to 5 cases: `0..50`, `50..=100`, `101..=150`,
|
||||||
//! clever: `0` and `1` for example will match the exact same rows, and return equivalent
|
//! `151..=200` and `200..`.
|
||||||
//! witnesses. In fact all of `0..50` would. We can thus restrict our exploration to 4
|
|
||||||
//! constructors: `0..50`, `50..=100`, `101..=150` and `151..=200`. That is enough and infinitely
|
|
||||||
//! more tractable.
|
|
||||||
//!
|
//!
|
||||||
//! We capture this idea in a function `split(p_1 ... p_n, c)` which returns a list of constructors
|
//! In [`super::usefulness`], we had said that `specialize` only takes value-only constructors. We
|
||||||
//! `c'` covered by `c`. Given such a `c'`, we require that all value ctors `c''` covered by `c'`
|
//! now relax this restriction: we allow `specialize` to take constructors like `0..50` as long as
|
||||||
//! return an equivalent set of witnesses after specializing and computing usefulness.
|
//! we're careful to only do that with constructors that make sense. For example, `specialize(0..50,
|
||||||
//! In the example above, witnesses for specializing by `c''` covered by `0..50` will only differ
|
//! (0..=100, true))` is sensible, but `specialize(50..=200, (0..=100, true))` is not.
|
||||||
//! in their first element.
|
|
||||||
//!
|
//!
|
||||||
//! We usually also ask that the `c'` together cover all of the original `c`. However we allow
|
//! Constructor splitting looks at the constructors in the first column of the matrix and constructs
|
||||||
//! skipping some constructors as long as it doesn't change whether the resulting list of witnesses
|
//! such a sensible set of constructors. Formally, we want to find a smallest disjoint set of
|
||||||
//! is empty of not. We use this in the wildcard `_` case.
|
//! constructors:
|
||||||
|
//! - Whose union covers the whole type, and
|
||||||
|
//! - That have no non-trivial intersection with any of the constructors in the column (i.e. they're
|
||||||
|
//! each either disjoint with or covered by any given column constructor).
|
||||||
//!
|
//!
|
||||||
//! Splitting is implemented in the [`Constructor::split`] function. We don't do splitting for
|
//! We compute this in two steps: first [`ConstructorSet::for_ty`] determines the set of all
|
||||||
//! or-patterns; instead we just try the alternatives one-by-one. For details on splitting
|
//! possible constructors for the type. Then [`ConstructorSet::split`] looks at the column of
|
||||||
//! wildcards, see [`Constructor::split`]; for integer ranges, see
|
//! constructors and splits the set into groups accordingly. The precise invariants of
|
||||||
//! [`IntRange::split`]; for slices, see [`Slice::split`].
|
//! [`ConstructorSet::split`] is described in [`SplitConstructorSet`].
|
||||||
|
//!
|
||||||
|
//! Constructor splitting has two interesting special cases: integer range splitting (see
|
||||||
|
//! [`IntRange::split`]) and slice splitting (see [`Slice::split`]).
|
||||||
|
//!
|
||||||
|
//!
|
||||||
|
//! # The `Missing` constructor
|
||||||
|
//!
|
||||||
|
//! We detail a special case of constructor splitting that is a bit subtle. Take the following:
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//! enum Direction { North, South, East, West }
|
||||||
|
//! # let wind = (Direction::North, 0u8);
|
||||||
|
//! match wind {
|
||||||
|
//! (Direction::North, 50..) => {}
|
||||||
|
//! (_, _) => {}
|
||||||
|
//! }
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! Here we expect constructor splitting to output two cases: `North`, and "everything else". This
|
||||||
|
//! "everything else" is represented by [`Constructor::Missing`]. Unlike other constructors, it's a
|
||||||
|
//! bit contextual: to know the exact list of constructors it represents we have to look at the
|
||||||
|
//! column. In practice however we don't need to, because by construction it only matches rows that
|
||||||
|
//! have wildcards. This is how this constructor is special: the only constructor that covers it is
|
||||||
|
//! `Wildcard`.
|
||||||
|
//!
|
||||||
|
//! The only place where we care about which constructors `Missing` represents is in diagnostics
|
||||||
|
//! (see `super::usefulness::WitnessMatrix::apply_constructor`).
|
||||||
|
//!
|
||||||
|
//! We choose whether to specialize with `Missing` in
|
||||||
|
//! `super::usefulness::compute_exhaustiveness_and_reachability`.
|
||||||
|
//!
|
||||||
|
//!
|
||||||
|
//!
|
||||||
|
//! ## Opaque patterns
|
||||||
|
//!
|
||||||
|
//! Some patterns, such as constants that are not allowed to be matched structurally, cannot be
|
||||||
|
//! inspected, which we handle with `Constructor::Opaque`. Since we know nothing of these patterns,
|
||||||
|
//! we assume they never cover each other. In order to respect the invariants of
|
||||||
|
//! [`SplitConstructorSet`], we give each `Opaque` constructor a unique id so we can recognize it.
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::cmp::{self, max, min, Ordering};
|
use std::cmp::{self, max, min, Ordering};
|
||||||
@ -617,6 +659,18 @@ impl Slice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A globally unique id to distinguish `Opaque` patterns.
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub(super) struct OpaqueId(u32);
|
||||||
|
|
||||||
|
impl OpaqueId {
|
||||||
|
fn new() -> Self {
|
||||||
|
use std::sync::atomic::{AtomicU32, Ordering};
|
||||||
|
static OPAQUE_ID: AtomicU32 = AtomicU32::new(0);
|
||||||
|
OpaqueId(OPAQUE_ID.fetch_add(1, Ordering::SeqCst))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A value can be decomposed into a constructor applied to some fields. This struct represents
|
/// A value can be decomposed into a constructor applied to some fields. This struct represents
|
||||||
/// the constructor. See also `Fields`.
|
/// the constructor. See also `Fields`.
|
||||||
///
|
///
|
||||||
@ -626,8 +680,8 @@ impl Slice {
|
|||||||
/// `Fields`.
|
/// `Fields`.
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub(super) enum Constructor<'tcx> {
|
pub(super) enum Constructor<'tcx> {
|
||||||
/// The constructor for patterns that have a single constructor, like tuples, struct patterns
|
/// The constructor for patterns that have a single constructor, like tuples, struct patterns,
|
||||||
/// and fixed-length arrays.
|
/// and references. Fixed-length arrays are treated separately with `Slice`.
|
||||||
Single,
|
Single,
|
||||||
/// Enum variants.
|
/// Enum variants.
|
||||||
Variant(VariantIdx),
|
Variant(VariantIdx),
|
||||||
@ -642,10 +696,12 @@ pub(super) enum Constructor<'tcx> {
|
|||||||
Str(mir::Const<'tcx>),
|
Str(mir::Const<'tcx>),
|
||||||
/// Array and slice patterns.
|
/// Array and slice patterns.
|
||||||
Slice(Slice),
|
Slice(Slice),
|
||||||
/// Constants that must not be matched structurally. They are treated as black
|
/// Constants that must not be matched structurally. They are treated as black boxes for the
|
||||||
/// boxes for the purposes of exhaustiveness: we must not inspect them, and they
|
/// purposes of exhaustiveness: we must not inspect them, and they don't count towards making a
|
||||||
/// don't count towards making a match exhaustive.
|
/// match exhaustive.
|
||||||
Opaque,
|
/// Carries an id that must be unique within a match. We need this to ensure the invariants of
|
||||||
|
/// [`SplitConstructorSet`].
|
||||||
|
Opaque(OpaqueId),
|
||||||
/// Or-pattern.
|
/// Or-pattern.
|
||||||
Or,
|
Or,
|
||||||
/// Wildcard pattern.
|
/// Wildcard pattern.
|
||||||
@ -657,12 +713,15 @@ pub(super) enum Constructor<'tcx> {
|
|||||||
/// We use this for variants behind an unstable gate as well as
|
/// We use this for variants behind an unstable gate as well as
|
||||||
/// `#[doc(hidden)]` ones.
|
/// `#[doc(hidden)]` ones.
|
||||||
Hidden,
|
Hidden,
|
||||||
/// Fake extra constructor for constructors that are not seen in the matrix, as explained in the
|
/// Fake extra constructor for constructors that are not seen in the matrix, as explained at the
|
||||||
/// code for [`Constructor::split`].
|
/// top of the file.
|
||||||
Missing,
|
Missing,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Constructor<'tcx> {
|
impl<'tcx> Constructor<'tcx> {
|
||||||
|
pub(super) fn is_wildcard(&self) -> bool {
|
||||||
|
matches!(self, Wildcard)
|
||||||
|
}
|
||||||
pub(super) fn is_non_exhaustive(&self) -> bool {
|
pub(super) fn is_non_exhaustive(&self) -> bool {
|
||||||
matches!(self, NonExhaustive)
|
matches!(self, NonExhaustive)
|
||||||
}
|
}
|
||||||
@ -728,7 +787,7 @@ impl<'tcx> Constructor<'tcx> {
|
|||||||
| F32Range(..)
|
| F32Range(..)
|
||||||
| F64Range(..)
|
| F64Range(..)
|
||||||
| Str(..)
|
| Str(..)
|
||||||
| Opaque
|
| Opaque(..)
|
||||||
| NonExhaustive
|
| NonExhaustive
|
||||||
| Hidden
|
| Hidden
|
||||||
| Missing { .. }
|
| Missing { .. }
|
||||||
@ -737,109 +796,23 @@ impl<'tcx> Constructor<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Some constructors (namely `Wildcard`, `IntRange` and `Slice`) actually stand for a set of
|
|
||||||
/// actual constructors (like variants, integers or fixed-sized slices). When specializing for
|
|
||||||
/// these constructors, we want to be specialising for the actual underlying constructors.
|
|
||||||
/// Naively, we would simply return the list of constructors they correspond to. We instead are
|
|
||||||
/// more clever: if there are constructors that we know will behave the same w.r.t. the current
|
|
||||||
/// matrix, we keep them grouped. For example, all slices of a sufficiently large length will
|
|
||||||
/// either be all useful or all non-useful with a given matrix.
|
|
||||||
///
|
|
||||||
/// See the branches for details on how the splitting is done.
|
|
||||||
///
|
|
||||||
/// This function may discard some irrelevant constructors if this preserves behavior. Eg. for
|
|
||||||
/// the `_` case, we ignore the constructors already present in the column, unless all of them
|
|
||||||
/// are.
|
|
||||||
pub(super) fn split<'a>(
|
|
||||||
&self,
|
|
||||||
pcx: &PatCtxt<'_, '_, 'tcx>,
|
|
||||||
ctors: impl Iterator<Item = &'a Constructor<'tcx>> + Clone,
|
|
||||||
) -> SmallVec<[Self; 1]>
|
|
||||||
where
|
|
||||||
'tcx: 'a,
|
|
||||||
{
|
|
||||||
match self {
|
|
||||||
Wildcard => {
|
|
||||||
let split_set = ConstructorSet::for_ty(pcx.cx, pcx.ty).split(pcx, ctors);
|
|
||||||
if !split_set.missing.is_empty() {
|
|
||||||
// We are splitting a wildcard in order to compute its usefulness. Some constructors are
|
|
||||||
// not present in the column. The first thing we note is that specializing with any of
|
|
||||||
// the missing constructors would select exactly the rows with wildcards. Moreover, they
|
|
||||||
// would all return equivalent results. We can therefore group them all into a
|
|
||||||
// fictitious `Missing` constructor.
|
|
||||||
//
|
|
||||||
// As an important optimization, this function will skip all the present constructors.
|
|
||||||
// This is correct because specializing with any of the present constructors would
|
|
||||||
// select a strict superset of the wildcard rows, and thus would only find witnesses
|
|
||||||
// already found with the `Missing` constructor.
|
|
||||||
// This does mean that diagnostics are incomplete: in
|
|
||||||
// ```
|
|
||||||
// match x {
|
|
||||||
// Some(true) => {}
|
|
||||||
// }
|
|
||||||
// ```
|
|
||||||
// we report `None` as missing but not `Some(false)`.
|
|
||||||
//
|
|
||||||
// When all the constructors are missing we can equivalently return the `Wildcard`
|
|
||||||
// constructor on its own. The difference between `Wildcard` and `Missing` will then
|
|
||||||
// only be in diagnostics.
|
|
||||||
|
|
||||||
// If some constructors are missing, we typically want to report those constructors,
|
|
||||||
// e.g.:
|
|
||||||
// ```
|
|
||||||
// enum Direction { N, S, E, W }
|
|
||||||
// let Direction::N = ...;
|
|
||||||
// ```
|
|
||||||
// we can report 3 witnesses: `S`, `E`, and `W`.
|
|
||||||
//
|
|
||||||
// However, if the user didn't actually specify a constructor
|
|
||||||
// in this arm, e.g., in
|
|
||||||
// ```
|
|
||||||
// let x: (Direction, Direction, bool) = ...;
|
|
||||||
// let (_, _, false) = x;
|
|
||||||
// ```
|
|
||||||
// we don't want to show all 16 possible witnesses `(<direction-1>, <direction-2>,
|
|
||||||
// true)` - we are satisfied with `(_, _, true)`. So if all constructors are missing we
|
|
||||||
// prefer to report just a wildcard `_`.
|
|
||||||
//
|
|
||||||
// The exception is: if we are at the top-level, for example in an empty match, we
|
|
||||||
// usually prefer to report the full list of constructors.
|
|
||||||
let all_missing = split_set.present.is_empty();
|
|
||||||
let report_when_all_missing =
|
|
||||||
pcx.is_top_level && !IntRange::is_integral(pcx.ty);
|
|
||||||
let ctor =
|
|
||||||
if all_missing && !report_when_all_missing { Wildcard } else { Missing };
|
|
||||||
smallvec![ctor]
|
|
||||||
} else {
|
|
||||||
split_set.present
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Fast-track if the range is trivial.
|
|
||||||
IntRange(this_range) if !this_range.is_singleton() => {
|
|
||||||
let column_ranges = ctors.filter_map(|ctor| ctor.as_int_range()).cloned();
|
|
||||||
this_range.split(column_ranges).map(|(_, range)| IntRange(range)).collect()
|
|
||||||
}
|
|
||||||
Slice(this_slice @ Slice { kind: VarLen(..), .. }) => {
|
|
||||||
let column_slices = ctors.filter_map(|c| c.as_slice());
|
|
||||||
this_slice.split(column_slices).map(|(_, slice)| Slice(slice)).collect()
|
|
||||||
}
|
|
||||||
// Any other constructor can be used unchanged.
|
|
||||||
_ => smallvec![self.clone()],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns whether `self` is covered by `other`, i.e. whether `self` is a subset of `other`.
|
/// Returns whether `self` is covered by `other`, i.e. whether `self` is a subset of `other`.
|
||||||
/// For the simple cases, this is simply checking for equality. For the "grouped" constructors,
|
/// For the simple cases, this is simply checking for equality. For the "grouped" constructors,
|
||||||
/// this checks for inclusion.
|
/// this checks for inclusion.
|
||||||
// We inline because this has a single call site in `Matrix::specialize_constructor`.
|
// We inline because this has a single call site in `Matrix::specialize_constructor`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(super) fn is_covered_by<'p>(&self, pcx: &PatCtxt<'_, 'p, 'tcx>, other: &Self) -> bool {
|
pub(super) fn is_covered_by<'p>(&self, pcx: &PatCtxt<'_, 'p, 'tcx>, other: &Self) -> bool {
|
||||||
// This must be kept in sync with `is_covered_by_any`.
|
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
|
(Wildcard, _) => {
|
||||||
|
span_bug!(
|
||||||
|
pcx.cx.scrut_span,
|
||||||
|
"Constructor splitting should not have returned `Wildcard`"
|
||||||
|
)
|
||||||
|
}
|
||||||
// Wildcards cover anything
|
// Wildcards cover anything
|
||||||
(_, Wildcard) => true,
|
(_, Wildcard) => true,
|
||||||
// Only a wildcard pattern can match these special constructors.
|
// Only a wildcard pattern can match these special constructors.
|
||||||
(Wildcard | Missing { .. } | NonExhaustive | Hidden, _) => false,
|
(Missing { .. } | NonExhaustive | Hidden, _) => false,
|
||||||
|
|
||||||
(Single, Single) => true,
|
(Single, Single) => true,
|
||||||
(Variant(self_id), Variant(other_id)) => self_id == other_id,
|
(Variant(self_id), Variant(other_id)) => self_id == other_id,
|
||||||
@ -869,11 +842,13 @@ impl<'tcx> Constructor<'tcx> {
|
|||||||
}
|
}
|
||||||
(Slice(self_slice), Slice(other_slice)) => self_slice.is_covered_by(*other_slice),
|
(Slice(self_slice), Slice(other_slice)) => self_slice.is_covered_by(*other_slice),
|
||||||
|
|
||||||
// We are trying to inspect an opaque constant. Thus we skip the row.
|
// Opaque constructors don't interact with anything unless they come from the
|
||||||
(Opaque, _) | (_, Opaque) => false,
|
// syntactically identical pattern.
|
||||||
|
(Opaque(self_id), Opaque(other_id)) => self_id == other_id,
|
||||||
|
(Opaque(..), _) | (_, Opaque(..)) => false,
|
||||||
|
|
||||||
_ => span_bug!(
|
_ => span_bug!(
|
||||||
pcx.span,
|
pcx.cx.scrut_span,
|
||||||
"trying to compare incompatible constructors {:?} and {:?}",
|
"trying to compare incompatible constructors {:?} and {:?}",
|
||||||
self,
|
self,
|
||||||
other
|
other
|
||||||
@ -917,16 +892,20 @@ pub(super) enum ConstructorSet {
|
|||||||
/// `present` is morally the set of constructors present in the column, and `missing` is the set of
|
/// `present` is morally the set of constructors present in the column, and `missing` is the set of
|
||||||
/// constructors that exist in the type but are not present in the column.
|
/// constructors that exist in the type but are not present in the column.
|
||||||
///
|
///
|
||||||
/// More formally, they respect the following constraints:
|
/// More formally, if we discard wildcards from the column, this respects the following constraints:
|
||||||
/// - the union of `present` and `missing` covers the whole type
|
/// 1. the union of `present` and `missing` covers the whole type
|
||||||
/// - `present` and `missing` are disjoint
|
/// 2. each constructor in `present` is covered by something in the column
|
||||||
/// - neither contains wildcards
|
/// 3. no constructor in `missing` is covered by anything in the column
|
||||||
/// - each constructor in `present` is covered by some non-wildcard constructor in the column
|
/// 4. each constructor in the column is equal to the union of one or more constructors in `present`
|
||||||
/// - together, the constructors in `present` cover all the non-wildcard constructor in the column
|
/// 5. `missing` does not contain empty constructors (see discussion about emptiness at the top of
|
||||||
/// - non-wildcards in the column do no cover anything in `missing`
|
/// the file);
|
||||||
/// - constructors in `present` and `missing` are split for the column; in other words, they are
|
/// 6. constructors in `present` and `missing` are split for the column; in other words, they are
|
||||||
/// either fully included in or disjoint from each constructor in the column. This avoids
|
/// either fully included in or fully disjoint from each constructor in the column. In other
|
||||||
/// non-trivial intersections like between `0..10` and `5..15`.
|
/// words, there are no non-trivial intersections like between `0..10` and `5..15`.
|
||||||
|
///
|
||||||
|
/// We must be particularly careful with weird constructors like `Opaque`: they're not formally part
|
||||||
|
/// of the `ConstructorSet` for the type, yet if we forgot to include them in `present` we would be
|
||||||
|
/// ignoring any row with `Opaque`s in the algorithm. Hence the importance of point 4.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(super) struct SplitConstructorSet<'tcx> {
|
pub(super) struct SplitConstructorSet<'tcx> {
|
||||||
pub(super) present: SmallVec<[Constructor<'tcx>; 1]>,
|
pub(super) present: SmallVec<[Constructor<'tcx>; 1]>,
|
||||||
@ -934,6 +913,7 @@ pub(super) struct SplitConstructorSet<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ConstructorSet {
|
impl ConstructorSet {
|
||||||
|
/// Creates a set that represents all the constructors of `ty`.
|
||||||
#[instrument(level = "debug", skip(cx), ret)]
|
#[instrument(level = "debug", skip(cx), ret)]
|
||||||
pub(super) fn for_ty<'p, 'tcx>(cx: &MatchCheckCtxt<'p, 'tcx>, ty: Ty<'tcx>) -> Self {
|
pub(super) fn for_ty<'p, 'tcx>(cx: &MatchCheckCtxt<'p, 'tcx>, ty: Ty<'tcx>) -> Self {
|
||||||
let make_range = |start, end| {
|
let make_range = |start, end| {
|
||||||
@ -1069,9 +1049,10 @@ impl ConstructorSet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is the core logical operation of exhaustiveness checking. This analyzes a column a
|
/// This analyzes a column of constructors to 1/ determine which constructors of the type (if
|
||||||
/// constructors to 1/ determine which constructors of the type (if any) are missing; 2/ split
|
/// any) are missing; 2/ split constructors to handle non-trivial intersections e.g. on ranges
|
||||||
/// constructors to handle non-trivial intersections e.g. on ranges or slices.
|
/// or slices. This can get subtle; see [`SplitConstructorSet`] for details of this operation
|
||||||
|
/// and its invariants.
|
||||||
#[instrument(level = "debug", skip(self, pcx, ctors), ret)]
|
#[instrument(level = "debug", skip(self, pcx, ctors), ret)]
|
||||||
pub(super) fn split<'a, 'tcx>(
|
pub(super) fn split<'a, 'tcx>(
|
||||||
&self,
|
&self,
|
||||||
@ -1083,18 +1064,26 @@ impl ConstructorSet {
|
|||||||
{
|
{
|
||||||
let mut present: SmallVec<[_; 1]> = SmallVec::new();
|
let mut present: SmallVec<[_; 1]> = SmallVec::new();
|
||||||
let mut missing = Vec::new();
|
let mut missing = Vec::new();
|
||||||
// Constructors in `ctors`, except wildcards.
|
// Constructors in `ctors`, except wildcards and opaques.
|
||||||
let mut seen = ctors.filter(|c| !(matches!(c, Opaque | Wildcard)));
|
let mut seen = Vec::new();
|
||||||
|
for ctor in ctors.cloned() {
|
||||||
|
if let Constructor::Opaque(..) = ctor {
|
||||||
|
present.push(ctor);
|
||||||
|
} else if !ctor.is_wildcard() {
|
||||||
|
seen.push(ctor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
ConstructorSet::Single => {
|
ConstructorSet::Single => {
|
||||||
if seen.next().is_none() {
|
if seen.is_empty() {
|
||||||
missing.push(Single);
|
missing.push(Single);
|
||||||
} else {
|
} else {
|
||||||
present.push(Single);
|
present.push(Single);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ConstructorSet::Variants { visible_variants, hidden_variants, non_exhaustive } => {
|
ConstructorSet::Variants { visible_variants, hidden_variants, non_exhaustive } => {
|
||||||
let seen_set: FxHashSet<_> = seen.map(|c| c.as_variant().unwrap()).collect();
|
let seen_set: FxHashSet<_> = seen.iter().map(|c| c.as_variant().unwrap()).collect();
|
||||||
let mut skipped_a_hidden_variant = false;
|
let mut skipped_a_hidden_variant = false;
|
||||||
|
|
||||||
for variant in visible_variants {
|
for variant in visible_variants {
|
||||||
@ -1125,7 +1114,7 @@ impl ConstructorSet {
|
|||||||
ConstructorSet::Bool => {
|
ConstructorSet::Bool => {
|
||||||
let mut seen_false = false;
|
let mut seen_false = false;
|
||||||
let mut seen_true = false;
|
let mut seen_true = false;
|
||||||
for b in seen.map(|ctor| ctor.as_bool().unwrap()) {
|
for b in seen.iter().map(|ctor| ctor.as_bool().unwrap()) {
|
||||||
if b {
|
if b {
|
||||||
seen_true = true;
|
seen_true = true;
|
||||||
} else {
|
} else {
|
||||||
@ -1145,7 +1134,7 @@ impl ConstructorSet {
|
|||||||
}
|
}
|
||||||
ConstructorSet::Integers { range_1, range_2 } => {
|
ConstructorSet::Integers { range_1, range_2 } => {
|
||||||
let seen_ranges: Vec<_> =
|
let seen_ranges: Vec<_> =
|
||||||
seen.map(|ctor| ctor.as_int_range().unwrap().clone()).collect();
|
seen.iter().map(|ctor| ctor.as_int_range().unwrap().clone()).collect();
|
||||||
for (seen, splitted_range) in range_1.split(seen_ranges.iter().cloned()) {
|
for (seen, splitted_range) in range_1.split(seen_ranges.iter().cloned()) {
|
||||||
match seen {
|
match seen {
|
||||||
Presence::Unseen => missing.push(IntRange(splitted_range)),
|
Presence::Unseen => missing.push(IntRange(splitted_range)),
|
||||||
@ -1162,7 +1151,7 @@ impl ConstructorSet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
&ConstructorSet::Slice(array_len) => {
|
&ConstructorSet::Slice(array_len) => {
|
||||||
let seen_slices = seen.map(|c| c.as_slice().unwrap());
|
let seen_slices = seen.iter().map(|c| c.as_slice().unwrap());
|
||||||
let base_slice = Slice::new(array_len, VarLen(0, 0));
|
let base_slice = Slice::new(array_len, VarLen(0, 0));
|
||||||
for (seen, splitted_slice) in base_slice.split(seen_slices) {
|
for (seen, splitted_slice) in base_slice.split(seen_slices) {
|
||||||
let ctor = Slice(splitted_slice);
|
let ctor = Slice(splitted_slice);
|
||||||
@ -1178,7 +1167,7 @@ impl ConstructorSet {
|
|||||||
// unreachable if length != 0.
|
// unreachable if length != 0.
|
||||||
// We still gather the seen constructors in `present`, but the only slice that can
|
// We still gather the seen constructors in `present`, but the only slice that can
|
||||||
// go in `missing` is `[]`.
|
// go in `missing` is `[]`.
|
||||||
let seen_slices = seen.map(|c| c.as_slice().unwrap());
|
let seen_slices = seen.iter().map(|c| c.as_slice().unwrap());
|
||||||
let base_slice = Slice::new(None, VarLen(0, 0));
|
let base_slice = Slice::new(None, VarLen(0, 0));
|
||||||
for (seen, splitted_slice) in base_slice.split(seen_slices) {
|
for (seen, splitted_slice) in base_slice.split(seen_slices) {
|
||||||
let ctor = Slice(splitted_slice);
|
let ctor = Slice(splitted_slice);
|
||||||
@ -1194,7 +1183,7 @@ impl ConstructorSet {
|
|||||||
ConstructorSet::Unlistable => {
|
ConstructorSet::Unlistable => {
|
||||||
// Since we can't list constructors, we take the ones in the column. This might list
|
// Since we can't list constructors, we take the ones in the column. This might list
|
||||||
// some constructors several times but there's not much we can do.
|
// some constructors several times but there's not much we can do.
|
||||||
present.extend(seen.cloned());
|
present.extend(seen);
|
||||||
missing.push(NonExhaustive);
|
missing.push(NonExhaustive);
|
||||||
}
|
}
|
||||||
// If `exhaustive_patterns` is disabled and our scrutinee is an empty type, we cannot
|
// If `exhaustive_patterns` is disabled and our scrutinee is an empty type, we cannot
|
||||||
@ -1210,19 +1199,6 @@ impl ConstructorSet {
|
|||||||
|
|
||||||
SplitConstructorSet { present, missing }
|
SplitConstructorSet { present, missing }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the set of constructors missing from this column.
|
|
||||||
/// This is only used for reporting to the user.
|
|
||||||
pub(super) fn compute_missing<'a, 'tcx>(
|
|
||||||
&self,
|
|
||||||
pcx: &PatCtxt<'_, '_, 'tcx>,
|
|
||||||
ctors: impl Iterator<Item = &'a Constructor<'tcx>> + Clone,
|
|
||||||
) -> Vec<Constructor<'tcx>>
|
|
||||||
where
|
|
||||||
'tcx: 'a,
|
|
||||||
{
|
|
||||||
self.split(pcx, ctors).missing
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A value can be decomposed into a constructor applied to some fields. This struct represents
|
/// A value can be decomposed into a constructor applied to some fields. This struct represents
|
||||||
@ -1273,9 +1249,8 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
|
|||||||
fn wildcards_from_tys(
|
fn wildcards_from_tys(
|
||||||
cx: &MatchCheckCtxt<'p, 'tcx>,
|
cx: &MatchCheckCtxt<'p, 'tcx>,
|
||||||
tys: impl IntoIterator<Item = Ty<'tcx>>,
|
tys: impl IntoIterator<Item = Ty<'tcx>>,
|
||||||
span: Span,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Fields::from_iter(cx, tys.into_iter().map(|ty| DeconstructedPat::wildcard(ty, span)))
|
Fields::from_iter(cx, tys.into_iter().map(|ty| DeconstructedPat::wildcard(ty, DUMMY_SP)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// In the cases of either a `#[non_exhaustive]` field list or a non-public field, we hide
|
// In the cases of either a `#[non_exhaustive]` field list or a non-public field, we hide
|
||||||
@ -1311,18 +1286,18 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
|
|||||||
pub(super) fn wildcards(pcx: &PatCtxt<'_, 'p, 'tcx>, constructor: &Constructor<'tcx>) -> Self {
|
pub(super) fn wildcards(pcx: &PatCtxt<'_, 'p, 'tcx>, constructor: &Constructor<'tcx>) -> Self {
|
||||||
let ret = match constructor {
|
let ret = match constructor {
|
||||||
Single | Variant(_) => match pcx.ty.kind() {
|
Single | Variant(_) => match pcx.ty.kind() {
|
||||||
ty::Tuple(fs) => Fields::wildcards_from_tys(pcx.cx, fs.iter(), pcx.span),
|
ty::Tuple(fs) => Fields::wildcards_from_tys(pcx.cx, fs.iter()),
|
||||||
ty::Ref(_, rty, _) => Fields::wildcards_from_tys(pcx.cx, once(*rty), pcx.span),
|
ty::Ref(_, rty, _) => Fields::wildcards_from_tys(pcx.cx, once(*rty)),
|
||||||
ty::Adt(adt, args) => {
|
ty::Adt(adt, args) => {
|
||||||
if adt.is_box() {
|
if adt.is_box() {
|
||||||
// The only legal patterns of type `Box` (outside `std`) are `_` and box
|
// The only legal patterns of type `Box` (outside `std`) are `_` and box
|
||||||
// patterns. If we're here we can assume this is a box pattern.
|
// patterns. If we're here we can assume this is a box pattern.
|
||||||
Fields::wildcards_from_tys(pcx.cx, once(args.type_at(0)), pcx.span)
|
Fields::wildcards_from_tys(pcx.cx, once(args.type_at(0)))
|
||||||
} else {
|
} else {
|
||||||
let variant = &adt.variant(constructor.variant_index_for_adt(*adt));
|
let variant = &adt.variant(constructor.variant_index_for_adt(*adt));
|
||||||
let tys = Fields::list_variant_nonhidden_fields(pcx.cx, pcx.ty, variant)
|
let tys = Fields::list_variant_nonhidden_fields(pcx.cx, pcx.ty, variant)
|
||||||
.map(|(_, ty)| ty);
|
.map(|(_, ty)| ty);
|
||||||
Fields::wildcards_from_tys(pcx.cx, tys, pcx.span)
|
Fields::wildcards_from_tys(pcx.cx, tys)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => bug!("Unexpected type for `Single` constructor: {:?}", pcx),
|
_ => bug!("Unexpected type for `Single` constructor: {:?}", pcx),
|
||||||
@ -1330,7 +1305,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
|
|||||||
Slice(slice) => match *pcx.ty.kind() {
|
Slice(slice) => match *pcx.ty.kind() {
|
||||||
ty::Slice(ty) | ty::Array(ty, _) => {
|
ty::Slice(ty) | ty::Array(ty, _) => {
|
||||||
let arity = slice.arity();
|
let arity = slice.arity();
|
||||||
Fields::wildcards_from_tys(pcx.cx, (0..arity).map(|_| ty), pcx.span)
|
Fields::wildcards_from_tys(pcx.cx, (0..arity).map(|_| ty))
|
||||||
}
|
}
|
||||||
_ => bug!("bad slice pattern {:?} {:?}", constructor, pcx),
|
_ => bug!("bad slice pattern {:?} {:?}", constructor, pcx),
|
||||||
},
|
},
|
||||||
@ -1339,7 +1314,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
|
|||||||
| F32Range(..)
|
| F32Range(..)
|
||||||
| F64Range(..)
|
| F64Range(..)
|
||||||
| Str(..)
|
| Str(..)
|
||||||
| Opaque
|
| Opaque(..)
|
||||||
| NonExhaustive
|
| NonExhaustive
|
||||||
| Hidden
|
| Hidden
|
||||||
| Missing { .. }
|
| Missing { .. }
|
||||||
@ -1388,6 +1363,8 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
|
|||||||
DeconstructedPat { ctor, fields, ty, span, reachable: Cell::new(false) }
|
DeconstructedPat { ctor, fields, ty, span, reachable: Cell::new(false) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Note: the input patterns must have been lowered through
|
||||||
|
/// `super::check_match::MatchVisitor::lower_pattern`.
|
||||||
pub(crate) fn from_pat(cx: &MatchCheckCtxt<'p, 'tcx>, pat: &Pat<'tcx>) -> Self {
|
pub(crate) fn from_pat(cx: &MatchCheckCtxt<'p, 'tcx>, pat: &Pat<'tcx>) -> Self {
|
||||||
let mkpat = |pat| DeconstructedPat::from_pat(cx, pat);
|
let mkpat = |pat| DeconstructedPat::from_pat(cx, pat);
|
||||||
let ctor;
|
let ctor;
|
||||||
@ -1470,14 +1447,14 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
|
|||||||
ty::Bool => {
|
ty::Bool => {
|
||||||
ctor = match value.try_eval_bool(cx.tcx, cx.param_env) {
|
ctor = match value.try_eval_bool(cx.tcx, cx.param_env) {
|
||||||
Some(b) => Bool(b),
|
Some(b) => Bool(b),
|
||||||
None => Opaque,
|
None => Opaque(OpaqueId::new()),
|
||||||
};
|
};
|
||||||
fields = Fields::empty();
|
fields = Fields::empty();
|
||||||
}
|
}
|
||||||
ty::Char | ty::Int(_) | ty::Uint(_) => {
|
ty::Char | ty::Int(_) | ty::Uint(_) => {
|
||||||
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
|
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
|
||||||
Some(bits) => IntRange(IntRange::from_bits(cx.tcx, pat.ty, bits)),
|
Some(bits) => IntRange(IntRange::from_bits(cx.tcx, pat.ty, bits)),
|
||||||
None => Opaque,
|
None => Opaque(OpaqueId::new()),
|
||||||
};
|
};
|
||||||
fields = Fields::empty();
|
fields = Fields::empty();
|
||||||
}
|
}
|
||||||
@ -1488,7 +1465,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
|
|||||||
let value = rustc_apfloat::ieee::Single::from_bits(bits);
|
let value = rustc_apfloat::ieee::Single::from_bits(bits);
|
||||||
F32Range(value, value, RangeEnd::Included)
|
F32Range(value, value, RangeEnd::Included)
|
||||||
}
|
}
|
||||||
None => Opaque,
|
None => Opaque(OpaqueId::new()),
|
||||||
};
|
};
|
||||||
fields = Fields::empty();
|
fields = Fields::empty();
|
||||||
}
|
}
|
||||||
@ -1499,7 +1476,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
|
|||||||
let value = rustc_apfloat::ieee::Double::from_bits(bits);
|
let value = rustc_apfloat::ieee::Double::from_bits(bits);
|
||||||
F64Range(value, value, RangeEnd::Included)
|
F64Range(value, value, RangeEnd::Included)
|
||||||
}
|
}
|
||||||
None => Opaque,
|
None => Opaque(OpaqueId::new()),
|
||||||
};
|
};
|
||||||
fields = Fields::empty();
|
fields = Fields::empty();
|
||||||
}
|
}
|
||||||
@ -1520,7 +1497,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
|
|||||||
// into the corresponding `Pat`s by `const_to_pat`. Constants that remain are
|
// into the corresponding `Pat`s by `const_to_pat`. Constants that remain are
|
||||||
// opaque.
|
// opaque.
|
||||||
_ => {
|
_ => {
|
||||||
ctor = Opaque;
|
ctor = Opaque(OpaqueId::new());
|
||||||
fields = Fields::empty();
|
fields = Fields::empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1581,7 +1558,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
|
|||||||
fields = Fields::from_iter(cx, pats.into_iter().map(mkpat));
|
fields = Fields::from_iter(cx, pats.into_iter().map(mkpat));
|
||||||
}
|
}
|
||||||
PatKind::Error(_) => {
|
PatKind::Error(_) => {
|
||||||
ctor = Opaque;
|
ctor = Opaque(OpaqueId::new());
|
||||||
fields = Fields::empty();
|
fields = Fields::empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1591,6 +1568,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
|
|||||||
pub(super) fn is_or_pat(&self) -> bool {
|
pub(super) fn is_or_pat(&self) -> bool {
|
||||||
matches!(self.ctor, Or)
|
matches!(self.ctor, Or)
|
||||||
}
|
}
|
||||||
|
/// Expand this (possibly-nested) or-pattern into its alternatives.
|
||||||
pub(super) fn flatten_or_pat(&'p self) -> SmallVec<[&'p Self; 1]> {
|
pub(super) fn flatten_or_pat(&'p self) -> SmallVec<[&'p Self; 1]> {
|
||||||
if self.is_or_pat() {
|
if self.is_or_pat() {
|
||||||
self.iter_fields().flat_map(|p| p.flatten_or_pat()).collect()
|
self.iter_fields().flat_map(|p| p.flatten_or_pat()).collect()
|
||||||
@ -1646,7 +1624,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
|
|||||||
let wildcard: &_ = pcx
|
let wildcard: &_ = pcx
|
||||||
.cx
|
.cx
|
||||||
.pattern_arena
|
.pattern_arena
|
||||||
.alloc(DeconstructedPat::wildcard(inner_ty, pcx.span));
|
.alloc(DeconstructedPat::wildcard(inner_ty, DUMMY_SP));
|
||||||
let extra_wildcards = other_slice.arity() - self_slice.arity();
|
let extra_wildcards = other_slice.arity() - self_slice.arity();
|
||||||
let extra_wildcards = (0..extra_wildcards).map(|_| wildcard);
|
let extra_wildcards = (0..extra_wildcards).map(|_| wildcard);
|
||||||
prefix.iter().chain(extra_wildcards).chain(suffix).collect()
|
prefix.iter().chain(extra_wildcards).chain(suffix).collect()
|
||||||
@ -1663,7 +1641,17 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
|
|||||||
self.reachable.set(true)
|
self.reachable.set(true)
|
||||||
}
|
}
|
||||||
pub(super) fn is_reachable(&self) -> bool {
|
pub(super) fn is_reachable(&self) -> bool {
|
||||||
self.reachable.get()
|
if self.reachable.get() {
|
||||||
|
true
|
||||||
|
} else if self.is_or_pat() && self.iter_fields().any(|f| f.is_reachable()) {
|
||||||
|
// We always expand or patterns in the matrix, so we will never see the actual
|
||||||
|
// or-pattern (the one with constructor `Or`) in the column. As such, it will not be
|
||||||
|
// marked as reachable itself, only its children will. We recover this information here.
|
||||||
|
self.set_reachable();
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Report the spans of subpatterns that were not reachable, if any.
|
/// Report the spans of subpatterns that were not reachable, if any.
|
||||||
@ -1672,7 +1660,6 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
|
|||||||
self.collect_unreachable_spans(&mut spans);
|
self.collect_unreachable_spans(&mut spans);
|
||||||
spans
|
spans
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_unreachable_spans(&self, spans: &mut Vec<Span>) {
|
fn collect_unreachable_spans(&self, spans: &mut Vec<Span>) {
|
||||||
// We don't look at subpatterns if we already reported the whole pattern as unreachable.
|
// We don't look at subpatterns if we already reported the whole pattern as unreachable.
|
||||||
if !self.is_reachable() {
|
if !self.is_reachable() {
|
||||||
@ -1768,7 +1755,7 @@ impl<'p, 'tcx> fmt::Debug for DeconstructedPat<'p, 'tcx> {
|
|||||||
F32Range(lo, hi, end) => write!(f, "{lo}{end}{hi}"),
|
F32Range(lo, hi, end) => write!(f, "{lo}{end}{hi}"),
|
||||||
F64Range(lo, hi, end) => write!(f, "{lo}{end}{hi}"),
|
F64Range(lo, hi, end) => write!(f, "{lo}{end}{hi}"),
|
||||||
Str(value) => write!(f, "{value}"),
|
Str(value) => write!(f, "{value}"),
|
||||||
Opaque => write!(f, "<constant pattern>"),
|
Opaque(..) => write!(f, "<constant pattern>"),
|
||||||
Or => {
|
Or => {
|
||||||
for pat in self.iter_fields() {
|
for pat in self.iter_fields() {
|
||||||
write!(f, "{}{:?}", start_or_continue(" | "), pat)?;
|
write!(f, "{}{:?}", start_or_continue(" | "), pat)?;
|
||||||
@ -1898,7 +1885,7 @@ impl<'tcx> WitnessPat<'tcx> {
|
|||||||
"trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
|
"trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
|
||||||
`Missing` should have been processed in `apply_constructors`"
|
`Missing` should have been processed in `apply_constructors`"
|
||||||
),
|
),
|
||||||
F32Range(..) | F64Range(..) | Opaque | Or => {
|
F32Range(..) | F64Range(..) | Opaque(..) | Or => {
|
||||||
bug!("can't convert to pattern: {:?}", self)
|
bug!("can't convert to pattern: {:?}", self)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -35,6 +35,17 @@ fn main() {
|
|||||||
((0, 0) | (1, 0),) => {}
|
((0, 0) | (1, 0),) => {}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
match ((0, 0),) {
|
||||||
|
// Note how the second one would be redundant without the guard.
|
||||||
|
((x, y) | (y, x),) if x == 0 => {}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
match 0 {
|
||||||
|
// We don't warn the second one as redundant in general because of cases like the one above.
|
||||||
|
// We could technically do it if there are no bindings.
|
||||||
|
0 | 0 if 0 == 0 => {}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
// This one caused ICE https://github.com/rust-lang/rust/issues/117378
|
// This one caused ICE https://github.com/rust-lang/rust/issues/117378
|
||||||
match (0u8, 0) {
|
match (0u8, 0) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#![deny(unreachable_patterns)]
|
#![deny(unreachable_patterns)]
|
||||||
|
|
||||||
// We wrap patterns in a tuple because top-level or-patterns were special-cased.
|
// We wrap patterns in a tuple because top-level or-patterns were special-cased.
|
||||||
|
#[rustfmt::skip]
|
||||||
fn main() {
|
fn main() {
|
||||||
match (0u8,) {
|
match (0u8,) {
|
||||||
(1 | 2,) => {}
|
(1 | 2,) => {}
|
||||||
@ -73,6 +74,11 @@ fn main() {
|
|||||||
| 0] => {} //~ ERROR unreachable
|
| 0] => {} //~ ERROR unreachable
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
match (true, 0) {
|
||||||
|
(true, 0 | 0) => {} //~ ERROR unreachable
|
||||||
|
(_, 0 | 0) => {} //~ ERROR unreachable
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
match &[][..] {
|
match &[][..] {
|
||||||
[0] => {}
|
[0] => {}
|
||||||
[0, _] => {}
|
[0, _] => {}
|
||||||
@ -149,4 +155,8 @@ fn main() {
|
|||||||
| true, //~ ERROR unreachable
|
| true, //~ ERROR unreachable
|
||||||
false | true) => {}
|
false | true) => {}
|
||||||
}
|
}
|
||||||
|
match (true, true) {
|
||||||
|
(x, y)
|
||||||
|
| (y, x) => {} //~ ERROR unreachable
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:7:9
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:8:9
|
||||||
|
|
|
|
||||||
LL | (1,) => {}
|
LL | (1,) => {}
|
||||||
| ^^^^
|
| ^^^^
|
||||||
@ -11,128 +11,140 @@ LL | #![deny(unreachable_patterns)]
|
|||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:12:9
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:13:9
|
||||||
|
|
|
|
||||||
LL | (2,) => {}
|
LL | (2,) => {}
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:18:9
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:19:9
|
||||||
|
|
|
|
||||||
LL | (1 | 2,) => {}
|
LL | (1 | 2,) => {}
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:23:9
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:24:9
|
||||||
|
|
|
|
||||||
LL | (1, 3) => {}
|
LL | (1, 3) => {}
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:24:9
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:25:9
|
||||||
|
|
|
|
||||||
LL | (1, 4) => {}
|
LL | (1, 4) => {}
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:25:9
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:26:9
|
||||||
|
|
|
|
||||||
LL | (2, 4) => {}
|
LL | (2, 4) => {}
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:26:9
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:27:9
|
||||||
|
|
|
|
||||||
LL | (2 | 1, 4) => {}
|
LL | (2 | 1, 4) => {}
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:28:9
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:29:9
|
||||||
|
|
|
|
||||||
LL | (1, 4 | 5) => {}
|
LL | (1, 4 | 5) => {}
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:36:9
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:37:9
|
||||||
|
|
|
|
||||||
LL | (Some(1),) => {}
|
LL | (Some(1),) => {}
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:37:9
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:38:9
|
||||||
|
|
|
|
||||||
LL | (None,) => {}
|
LL | (None,) => {}
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:42:9
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:43:9
|
||||||
|
|
|
|
||||||
LL | ((1..=4,),) => {}
|
LL | ((1..=4,),) => {}
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:47:14
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:48:14
|
||||||
|
|
|
|
||||||
LL | (1 | 1,) => {}
|
LL | (1 | 1,) => {}
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:51:19
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:52:19
|
||||||
|
|
|
|
||||||
LL | (0 | 1) | 1 => {}
|
LL | (0 | 1) | 1 => {}
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:57:14
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:58:14
|
||||||
|
|
|
|
||||||
LL | 0 | (0 | 0) => {}
|
LL | 0 | (0 | 0) => {}
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:57:18
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:58:18
|
||||||
|
|
|
|
||||||
LL | 0 | (0 | 0) => {}
|
LL | 0 | (0 | 0) => {}
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:65:13
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:66:13
|
||||||
|
|
|
|
||||||
LL | / Some(
|
LL | / Some(
|
||||||
LL | | 0 | 0) => {}
|
LL | | 0 | 0) => {}
|
||||||
| |______________________^
|
| |______________________^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:71:15
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:72:15
|
||||||
|
|
|
|
||||||
LL | | 0
|
LL | | 0
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:73:15
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:74:15
|
||||||
|
|
|
|
||||||
LL | | 0] => {}
|
LL | | 0] => {}
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:81:10
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:78:20
|
||||||
|
|
|
||||||
|
LL | (true, 0 | 0) => {}
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:79:17
|
||||||
|
|
|
||||||
|
LL | (_, 0 | 0) => {}
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:87:10
|
||||||
|
|
|
|
||||||
LL | [1
|
LL | [1
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:93:10
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:99:10
|
||||||
|
|
|
|
||||||
LL | [true
|
LL | [true
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:100:36
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:106:36
|
||||||
|
|
|
|
||||||
LL | (true | false, None | Some(true
|
LL | (true | false, None | Some(true
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:105:14
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:111:14
|
||||||
|
|
|
|
||||||
LL | (true
|
LL | (true
|
||||||
| ^^^^
|
| ^^^^
|
||||||
@ -143,28 +155,34 @@ LL | (true | false, None | Some(t_or_f!())) => {}
|
|||||||
= note: this error originates in the macro `t_or_f` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `t_or_f` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:116:14
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:122:14
|
||||||
|
|
|
|
||||||
LL | Some(0
|
LL | Some(0
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:135:19
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:141:19
|
||||||
|
|
|
|
||||||
LL | | false) => {}
|
LL | | false) => {}
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:143:15
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:149:15
|
||||||
|
|
|
|
||||||
LL | | true) => {}
|
LL | | true) => {}
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:149:15
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:155:15
|
||||||
|
|
|
|
||||||
LL | | true,
|
LL | | true,
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error: aborting due to 26 previous errors
|
error: unreachable pattern
|
||||||
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:160:15
|
||||||
|
|
|
||||||
|
LL | | (y, x) => {}
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 29 previous errors
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error[E0004]: non-exhaustive patterns: type `usize` is non-empty
|
error[E0004]: non-exhaustive patterns: type `usize` is non-empty
|
||||||
--> $DIR/pointer-sized-int.rs:54:11
|
--> $DIR/pointer-sized-int.rs:59:11
|
||||||
|
|
|
|
||||||
LL | match 7usize {}
|
LL | match 7usize {}
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
@ -9,7 +9,7 @@ LL | match 0usize {
|
|||||||
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
|
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
|
||||||
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
||||||
|
|
|
|
||||||
LL ~ 0 ..= usize::MAX => {},
|
LL ~ 0..=usize::MAX => {},
|
||||||
LL + usize::MAX.. => todo!()
|
LL + usize::MAX.. => todo!()
|
||||||
|
|
|
|
||||||
|
|
||||||
@ -24,12 +24,12 @@ LL | match 0isize {
|
|||||||
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
|
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
|
||||||
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
|
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
|
||||||
|
|
|
|
||||||
LL ~ isize::MIN ..= isize::MAX => {},
|
LL ~ isize::MIN..=isize::MAX => {},
|
||||||
LL + ..isize::MIN | isize::MAX.. => todo!()
|
LL + ..isize::MIN | isize::MAX.. => todo!()
|
||||||
|
|
|
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `usize::MAX..` not covered
|
error[E0004]: non-exhaustive patterns: `usize::MAX..` not covered
|
||||||
--> $DIR/pointer-sized-int.rs:25:8
|
--> $DIR/pointer-sized-int.rs:24:8
|
||||||
|
|
|
|
||||||
LL | m!(0usize, 0..=usize::MAX);
|
LL | m!(0usize, 0..=usize::MAX);
|
||||||
| ^^^^^^ pattern `usize::MAX..` not covered
|
| ^^^^^^ pattern `usize::MAX..` not covered
|
||||||
@ -43,7 +43,7 @@ LL | match $s { $($t)+ => {}, usize::MAX.. => todo!() }
|
|||||||
| +++++++++++++++++++++++++
|
| +++++++++++++++++++++++++
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `usize::MAX..` not covered
|
error[E0004]: non-exhaustive patterns: `usize::MAX..` not covered
|
||||||
--> $DIR/pointer-sized-int.rs:27:8
|
--> $DIR/pointer-sized-int.rs:26:8
|
||||||
|
|
|
|
||||||
LL | m!(0usize, 0..5 | 5..=usize::MAX);
|
LL | m!(0usize, 0..5 | 5..=usize::MAX);
|
||||||
| ^^^^^^ pattern `usize::MAX..` not covered
|
| ^^^^^^ pattern `usize::MAX..` not covered
|
||||||
@ -57,7 +57,7 @@ LL | match $s { $($t)+ => {}, usize::MAX.. => todo!() }
|
|||||||
| +++++++++++++++++++++++++
|
| +++++++++++++++++++++++++
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `usize::MAX..` not covered
|
error[E0004]: non-exhaustive patterns: `usize::MAX..` not covered
|
||||||
--> $DIR/pointer-sized-int.rs:29:8
|
--> $DIR/pointer-sized-int.rs:28:8
|
||||||
|
|
|
|
||||||
LL | m!(0usize, 0..usize::MAX | usize::MAX);
|
LL | m!(0usize, 0..usize::MAX | usize::MAX);
|
||||||
| ^^^^^^ pattern `usize::MAX..` not covered
|
| ^^^^^^ pattern `usize::MAX..` not covered
|
||||||
@ -71,7 +71,7 @@ LL | match $s { $($t)+ => {}, usize::MAX.. => todo!() }
|
|||||||
| +++++++++++++++++++++++++
|
| +++++++++++++++++++++++++
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `(usize::MAX.., _)` not covered
|
error[E0004]: non-exhaustive patterns: `(usize::MAX.., _)` not covered
|
||||||
--> $DIR/pointer-sized-int.rs:31:8
|
--> $DIR/pointer-sized-int.rs:30:8
|
||||||
|
|
|
|
||||||
LL | m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false));
|
LL | m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false));
|
||||||
| ^^^^^^^^^^^^^^ pattern `(usize::MAX.., _)` not covered
|
| ^^^^^^^^^^^^^^ pattern `(usize::MAX.., _)` not covered
|
||||||
@ -85,7 +85,7 @@ LL | match $s { $($t)+ => {}, (usize::MAX.., _) => todo!() }
|
|||||||
| ++++++++++++++++++++++++++++++
|
| ++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered
|
error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered
|
||||||
--> $DIR/pointer-sized-int.rs:36:8
|
--> $DIR/pointer-sized-int.rs:39:8
|
||||||
|
|
|
|
||||||
LL | m!(0isize, isize::MIN..=isize::MAX);
|
LL | m!(0isize, isize::MIN..=isize::MAX);
|
||||||
| ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered
|
| ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered
|
||||||
@ -99,7 +99,7 @@ LL | match $s { $($t)+ => {}, ..isize::MIN | isize::MAX.. => todo!() }
|
|||||||
| ++++++++++++++++++++++++++++++++++++++++
|
| ++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered
|
error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered
|
||||||
--> $DIR/pointer-sized-int.rs:38:8
|
--> $DIR/pointer-sized-int.rs:41:8
|
||||||
|
|
|
|
||||||
LL | m!(0isize, isize::MIN..5 | 5..=isize::MAX);
|
LL | m!(0isize, isize::MIN..5 | 5..=isize::MAX);
|
||||||
| ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered
|
| ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered
|
||||||
@ -113,7 +113,21 @@ LL | match $s { $($t)+ => {}, ..isize::MIN | isize::MAX.. => todo!() }
|
|||||||
| ++++++++++++++++++++++++++++++++++++++++
|
| ++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered
|
error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered
|
||||||
--> $DIR/pointer-sized-int.rs:40:8
|
--> $DIR/pointer-sized-int.rs:43:8
|
||||||
|
|
|
||||||
|
LL | m!(0isize, isize::MIN..=-1 | 0 | 1..=isize::MAX);
|
||||||
|
| ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered
|
||||||
|
|
|
||||||
|
= note: the matched value is of type `isize`
|
||||||
|
= note: `isize` does not have fixed minimum and maximum values, so half-open ranges are necessary to match exhaustively
|
||||||
|
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
|
||||||
|
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
|
||||||
|
|
|
||||||
|
LL | match $s { $($t)+ => {}, ..isize::MIN | isize::MAX.. => todo!() }
|
||||||
|
| ++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered
|
||||||
|
--> $DIR/pointer-sized-int.rs:45:8
|
||||||
|
|
|
|
||||||
LL | m!(0isize, isize::MIN..isize::MAX | isize::MAX);
|
LL | m!(0isize, isize::MIN..isize::MAX | isize::MAX);
|
||||||
| ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered
|
| ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered
|
||||||
@ -127,10 +141,10 @@ LL | match $s { $($t)+ => {}, ..isize::MIN | isize::MAX.. => todo!() }
|
|||||||
| ++++++++++++++++++++++++++++++++++++++++
|
| ++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `(..isize::MIN, _)` and `(isize::MAX.., _)` not covered
|
error[E0004]: non-exhaustive patterns: `(..isize::MIN, _)` and `(isize::MAX.., _)` not covered
|
||||||
--> $DIR/pointer-sized-int.rs:42:8
|
--> $DIR/pointer-sized-int.rs:48:9
|
||||||
|
|
|
|
||||||
LL | m!((0isize, true), (isize::MIN..5, true)
|
LL | (0isize, true),
|
||||||
| ^^^^^^^^^^^^^^ patterns `(..isize::MIN, _)` and `(isize::MAX.., _)` not covered
|
| ^^^^^^^^^^^^^^ patterns `(..isize::MIN, _)` and `(isize::MAX.., _)` not covered
|
||||||
|
|
|
|
||||||
= note: the matched value is of type `(isize, bool)`
|
= note: the matched value is of type `(isize, bool)`
|
||||||
= note: `isize` does not have fixed minimum and maximum values, so half-open ranges are necessary to match exhaustively
|
= note: `isize` does not have fixed minimum and maximum values, so half-open ranges are necessary to match exhaustively
|
||||||
@ -140,23 +154,8 @@ help: ensure that all possible cases are being handled by adding a match arm wit
|
|||||||
LL | match $s { $($t)+ => {}, (..isize::MIN, _) | (isize::MAX.., _) => todo!() }
|
LL | match $s { $($t)+ => {}, (..isize::MIN, _) | (isize::MAX.., _) => todo!() }
|
||||||
| ++++++++++++++++++++++++++++++++++++++++++++++++++
|
| ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered
|
|
||||||
--> $DIR/pointer-sized-int.rs:47:11
|
|
||||||
|
|
|
||||||
LL | match 0isize {
|
|
||||||
| ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered
|
|
||||||
|
|
|
||||||
= note: the matched value is of type `isize`
|
|
||||||
= note: `isize` does not have fixed minimum and maximum values, so half-open ranges are necessary to match exhaustively
|
|
||||||
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
|
|
||||||
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
|
|
||||||
|
|
|
||||||
LL ~ 1 ..= isize::MAX => {},
|
|
||||||
LL + ..isize::MIN | isize::MAX.. => todo!()
|
|
||||||
|
|
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: type `usize` is non-empty
|
error[E0004]: non-exhaustive patterns: type `usize` is non-empty
|
||||||
--> $DIR/pointer-sized-int.rs:54:11
|
--> $DIR/pointer-sized-int.rs:59:11
|
||||||
|
|
|
|
||||||
LL | match 7usize {}
|
LL | match 7usize {}
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
@ -13,15 +13,14 @@ macro_rules! m {
|
|||||||
fn main() {
|
fn main() {
|
||||||
match 0usize {
|
match 0usize {
|
||||||
//[deny]~^ ERROR non-exhaustive patterns
|
//[deny]~^ ERROR non-exhaustive patterns
|
||||||
0 ..= usize::MAX => {}
|
0..=usize::MAX => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
match 0isize {
|
match 0isize {
|
||||||
//[deny]~^ ERROR non-exhaustive patterns
|
//[deny]~^ ERROR non-exhaustive patterns
|
||||||
isize::MIN ..= isize::MAX => {}
|
isize::MIN..=isize::MAX => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
m!(0usize, 0..);
|
|
||||||
m!(0usize, 0..=usize::MAX);
|
m!(0usize, 0..=usize::MAX);
|
||||||
//[deny]~^ ERROR non-exhaustive patterns
|
//[deny]~^ ERROR non-exhaustive patterns
|
||||||
m!(0usize, 0..5 | 5..=usize::MAX);
|
m!(0usize, 0..5 | 5..=usize::MAX);
|
||||||
@ -30,26 +29,32 @@ fn main() {
|
|||||||
//[deny]~^ ERROR non-exhaustive patterns
|
//[deny]~^ ERROR non-exhaustive patterns
|
||||||
m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false));
|
m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false));
|
||||||
//[deny]~^ ERROR non-exhaustive patterns
|
//[deny]~^ ERROR non-exhaustive patterns
|
||||||
|
|
||||||
|
m!(0usize, 0..);
|
||||||
|
m!(0usize, 0..5 | 5..);
|
||||||
|
m!(0usize, ..5 | 5..);
|
||||||
|
m!((0usize, true), (0..5, true) | (5.., true) | (0.., false));
|
||||||
m!(0usize, 0..=usize::MAX | usize::MAX..);
|
m!(0usize, 0..=usize::MAX | usize::MAX..);
|
||||||
|
|
||||||
m!(0isize, ..0 | 0..);
|
|
||||||
m!(0isize, isize::MIN..=isize::MAX);
|
m!(0isize, isize::MIN..=isize::MAX);
|
||||||
//[deny]~^ ERROR non-exhaustive patterns
|
//[deny]~^ ERROR non-exhaustive patterns
|
||||||
m!(0isize, isize::MIN..5 | 5..=isize::MAX);
|
m!(0isize, isize::MIN..5 | 5..=isize::MAX);
|
||||||
//[deny]~^ ERROR non-exhaustive patterns
|
//[deny]~^ ERROR non-exhaustive patterns
|
||||||
|
m!(0isize, isize::MIN..=-1 | 0 | 1..=isize::MAX);
|
||||||
|
//[deny]~^ ERROR non-exhaustive patterns
|
||||||
m!(0isize, isize::MIN..isize::MAX | isize::MAX);
|
m!(0isize, isize::MIN..isize::MAX | isize::MAX);
|
||||||
//[deny]~^ ERROR non-exhaustive patterns
|
//[deny]~^ ERROR non-exhaustive patterns
|
||||||
m!((0isize, true), (isize::MIN..5, true)
|
m!(
|
||||||
| (5..=isize::MAX, true) | (isize::MIN..=isize::MAX, false));
|
(0isize, true),
|
||||||
//[deny]~^^ ERROR non-exhaustive patterns
|
(isize::MIN..5, true) | (5..=isize::MAX, true) | (isize::MIN..=isize::MAX, false)
|
||||||
m!(0isize, ..=isize::MIN | isize::MIN..=isize::MAX | isize::MAX..);
|
);
|
||||||
|
//[deny]~^^^ ERROR non-exhaustive patterns
|
||||||
|
|
||||||
match 0isize {
|
m!(0isize, ..0 | 0..);
|
||||||
//[deny]~^ ERROR non-exhaustive patterns
|
m!(0isize, ..5 | 5..);
|
||||||
isize::MIN ..= -1 => {}
|
m!((0isize, true), (..5, true)
|
||||||
0 => {}
|
| (5.., true) | (..0 | 0.., false));
|
||||||
1 ..= isize::MAX => {}
|
m!(0isize, ..=isize::MIN | isize::MIN..=isize::MAX | isize::MAX..);
|
||||||
}
|
|
||||||
|
|
||||||
match 7usize {}
|
match 7usize {}
|
||||||
//~^ ERROR non-exhaustive patterns
|
//~^ ERROR non-exhaustive patterns
|
||||||
|
@ -9,9 +9,10 @@ macro_rules! m {
|
|||||||
$t2 => {}
|
$t2 => {}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
fn main() {
|
fn main() {
|
||||||
m!(0u8, 42, 41);
|
m!(0u8, 42, 41);
|
||||||
m!(0u8, 42, 42); //~ ERROR unreachable pattern
|
m!(0u8, 42, 42); //~ ERROR unreachable pattern
|
||||||
@ -85,7 +86,7 @@ fn main() {
|
|||||||
match 'a' {
|
match 'a' {
|
||||||
'\u{0}'..='\u{D7FF}' => {},
|
'\u{0}'..='\u{D7FF}' => {},
|
||||||
'\u{E000}'..='\u{10_FFFF}' => {},
|
'\u{E000}'..='\u{10_FFFF}' => {},
|
||||||
'\u{D7FF}'..='\u{E000}' => {}, // FIXME should be unreachable
|
'\u{D7FF}'..='\u{E000}' => {}, //~ ERROR unreachable pattern
|
||||||
}
|
}
|
||||||
|
|
||||||
match (0u8, true) {
|
match (0u8, true) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:17:17
|
--> $DIR/reachability.rs:18:17
|
||||||
|
|
|
|
||||||
LL | m!(0u8, 42, 42);
|
LL | m!(0u8, 42, 42);
|
||||||
| ^^
|
| ^^
|
||||||
@ -11,127 +11,127 @@ LL | #![deny(unreachable_patterns)]
|
|||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:21:22
|
--> $DIR/reachability.rs:22:22
|
||||||
|
|
|
|
||||||
LL | m!(0u8, 20..=30, 20);
|
LL | m!(0u8, 20..=30, 20);
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:22:22
|
--> $DIR/reachability.rs:23:22
|
||||||
|
|
|
|
||||||
LL | m!(0u8, 20..=30, 21);
|
LL | m!(0u8, 20..=30, 21);
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:23:22
|
--> $DIR/reachability.rs:24:22
|
||||||
|
|
|
|
||||||
LL | m!(0u8, 20..=30, 25);
|
LL | m!(0u8, 20..=30, 25);
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:24:22
|
--> $DIR/reachability.rs:25:22
|
||||||
|
|
|
|
||||||
LL | m!(0u8, 20..=30, 29);
|
LL | m!(0u8, 20..=30, 29);
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:25:22
|
--> $DIR/reachability.rs:26:22
|
||||||
|
|
|
|
||||||
LL | m!(0u8, 20..=30, 30);
|
LL | m!(0u8, 20..=30, 30);
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:28:21
|
--> $DIR/reachability.rs:29:21
|
||||||
|
|
|
|
||||||
LL | m!(0u8, 20..30, 20);
|
LL | m!(0u8, 20..30, 20);
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:29:21
|
--> $DIR/reachability.rs:30:21
|
||||||
|
|
|
|
||||||
LL | m!(0u8, 20..30, 21);
|
LL | m!(0u8, 20..30, 21);
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:30:21
|
--> $DIR/reachability.rs:31:21
|
||||||
|
|
|
|
||||||
LL | m!(0u8, 20..30, 25);
|
LL | m!(0u8, 20..30, 25);
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:31:21
|
--> $DIR/reachability.rs:32:21
|
||||||
|
|
|
|
||||||
LL | m!(0u8, 20..30, 29);
|
LL | m!(0u8, 20..30, 29);
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:35:22
|
--> $DIR/reachability.rs:36:22
|
||||||
|
|
|
|
||||||
LL | m!(0u8, 20..=30, 20..=30);
|
LL | m!(0u8, 20..=30, 20..=30);
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:36:22
|
--> $DIR/reachability.rs:37:22
|
||||||
|
|
|
|
||||||
LL | m!(0u8, 20.. 30, 20.. 30);
|
LL | m!(0u8, 20.. 30, 20.. 30);
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:37:22
|
--> $DIR/reachability.rs:38:22
|
||||||
|
|
|
|
||||||
LL | m!(0u8, 20..=30, 20.. 30);
|
LL | m!(0u8, 20..=30, 20.. 30);
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:39:22
|
--> $DIR/reachability.rs:40:22
|
||||||
|
|
|
|
||||||
LL | m!(0u8, 20..=30, 21..=30);
|
LL | m!(0u8, 20..=30, 21..=30);
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:40:22
|
--> $DIR/reachability.rs:41:22
|
||||||
|
|
|
|
||||||
LL | m!(0u8, 20..=30, 20..=29);
|
LL | m!(0u8, 20..=30, 20..=29);
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:42:24
|
--> $DIR/reachability.rs:43:24
|
||||||
|
|
|
|
||||||
LL | m!('a', 'A'..='z', 'a'..='z');
|
LL | m!('a', 'A'..='z', 'a'..='z');
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:49:9
|
--> $DIR/reachability.rs:50:9
|
||||||
|
|
|
|
||||||
LL | 5..=8 => {},
|
LL | 5..=8 => {},
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:55:9
|
--> $DIR/reachability.rs:56:9
|
||||||
|
|
|
|
||||||
LL | 5..15 => {},
|
LL | 5..15 => {},
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:62:9
|
--> $DIR/reachability.rs:63:9
|
||||||
|
|
|
|
||||||
LL | 5..25 => {},
|
LL | 5..25 => {},
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:70:9
|
--> $DIR/reachability.rs:71:9
|
||||||
|
|
|
|
||||||
LL | 5..25 => {},
|
LL | 5..25 => {},
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:76:9
|
--> $DIR/reachability.rs:77:9
|
||||||
|
|
|
|
||||||
LL | 5..15 => {},
|
LL | 5..15 => {},
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:83:9
|
--> $DIR/reachability.rs:84:9
|
||||||
|
|
|
|
||||||
LL | _ => {},
|
LL | _ => {},
|
||||||
| - matches any value
|
| - matches any value
|
||||||
@ -139,16 +139,22 @@ LL | '\u{D7FF}'..='\u{E000}' => {},
|
|||||||
| ^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern
|
| ^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:104:9
|
--> $DIR/reachability.rs:89:9
|
||||||
|
|
|
||||||
|
LL | '\u{D7FF}'..='\u{E000}' => {},
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/reachability.rs:105:9
|
||||||
|
|
|
|
||||||
LL | &FOO => {}
|
LL | &FOO => {}
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/reachability.rs:105:9
|
--> $DIR/reachability.rs:106:9
|
||||||
|
|
|
|
||||||
LL | BAR => {}
|
LL | BAR => {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: aborting due to 24 previous errors
|
error: aborting due to 25 previous errors
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ fn main() {
|
|||||||
//~^ ERROR non-exhaustive patterns
|
//~^ ERROR non-exhaustive patterns
|
||||||
//~| NOTE the matched value is of type
|
//~| NOTE the matched value is of type
|
||||||
//~| NOTE match arms with guards don't count towards exhaustivity
|
//~| NOTE match arms with guards don't count towards exhaustivity
|
||||||
//~| NOTE pattern `box _` not covered
|
//~| NOTE pattern `box ElementKind::HTMLImageElement(_)` not covered
|
||||||
//~| NOTE `Box<ElementKind>` defined here
|
//~| NOTE `Box<ElementKind>` defined here
|
||||||
box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => true,
|
box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => true,
|
||||||
},
|
},
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error[E0004]: non-exhaustive patterns: `box _` not covered
|
error[E0004]: non-exhaustive patterns: `box ElementKind::HTMLImageElement(_)` not covered
|
||||||
--> $DIR/issue-3601.rs:30:44
|
--> $DIR/issue-3601.rs:30:44
|
||||||
|
|
|
|
||||||
LL | box NodeKind::Element(ed) => match ed.kind {
|
LL | box NodeKind::Element(ed) => match ed.kind {
|
||||||
| ^^^^^^^ pattern `box _` not covered
|
| ^^^^^^^ pattern `box ElementKind::HTMLImageElement(_)` not covered
|
||||||
|
|
|
|
||||||
note: `Box<ElementKind>` defined here
|
note: `Box<ElementKind>` defined here
|
||||||
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||||
@ -11,7 +11,7 @@ note: `Box<ElementKind>` defined here
|
|||||||
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
||||||
|
|
|
|
||||||
LL ~ box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => true,
|
LL ~ box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => true,
|
||||||
LL ~ box _ => todo!(),
|
LL ~ box ElementKind::HTMLImageElement(_) => todo!(),
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
@ -10,18 +10,18 @@ help: ensure that all possible cases are being handled by adding a match arm wit
|
|||||||
LL | match 0 { 1 => (), i32::MIN..=0_i32 | 2_i32..=i32::MAX => todo!() }
|
LL | match 0 { 1 => (), i32::MIN..=0_i32 | 2_i32..=i32::MAX => todo!() }
|
||||||
| ++++++++++++++++++++++++++++++++++++++++++++++++
|
| ++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `_` not covered
|
error[E0004]: non-exhaustive patterns: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
|
||||||
--> $DIR/match-non-exhaustive.rs:3:11
|
--> $DIR/match-non-exhaustive.rs:3:11
|
||||||
|
|
|
|
||||||
LL | match 0 { 0 if false => () }
|
LL | match 0 { 0 if false => () }
|
||||||
| ^ pattern `_` not covered
|
| ^ patterns `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
|
||||||
|
|
|
|
||||||
= note: the matched value is of type `i32`
|
= note: the matched value is of type `i32`
|
||||||
= note: match arms with guards don't count towards exhaustivity
|
= note: match arms with guards don't count towards exhaustivity
|
||||||
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
|
||||||
|
|
|
|
||||||
LL | match 0 { 0 if false => (), _ => todo!() }
|
LL | match 0 { 0 if false => (), i32::MIN..=-1_i32 | 1_i32..=i32::MAX => todo!() }
|
||||||
| ++++++++++++++
|
| +++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
@ -43,6 +43,10 @@ fn main() {
|
|||||||
//~^ ERROR `&[_, ..]` not covered
|
//~^ ERROR `&[_, ..]` not covered
|
||||||
[] => {}
|
[] => {}
|
||||||
}
|
}
|
||||||
|
match s {
|
||||||
|
//~^ ERROR `&[]` and `&[_, ..]` not covered
|
||||||
|
[..] if false => {}
|
||||||
|
}
|
||||||
match s {
|
match s {
|
||||||
//~^ ERROR `&[_, _, ..]` not covered
|
//~^ ERROR `&[_, _, ..]` not covered
|
||||||
[] => {}
|
[] => {}
|
||||||
|
@ -89,9 +89,23 @@ LL ~ [] => {},
|
|||||||
LL + &[_, ..] => todo!()
|
LL + &[_, ..] => todo!()
|
||||||
|
|
|
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered
|
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, ..]` not covered
|
||||||
--> $DIR/slice-patterns-exhaustiveness.rs:46:11
|
--> $DIR/slice-patterns-exhaustiveness.rs:46:11
|
||||||
|
|
|
|
||||||
|
LL | match s {
|
||||||
|
| ^ patterns `&[]` and `&[_, ..]` not covered
|
||||||
|
|
|
||||||
|
= note: the matched value is of type `&[bool]`
|
||||||
|
= note: match arms with guards don't count towards exhaustivity
|
||||||
|
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
|
||||||
|
|
|
||||||
|
LL ~ [..] if false => {},
|
||||||
|
LL + &[] | &[_, ..] => todo!()
|
||||||
|
|
|
||||||
|
|
||||||
|
error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered
|
||||||
|
--> $DIR/slice-patterns-exhaustiveness.rs:50:11
|
||||||
|
|
|
||||||
LL | match s {
|
LL | match s {
|
||||||
| ^ pattern `&[_, _, ..]` not covered
|
| ^ pattern `&[_, _, ..]` not covered
|
||||||
|
|
|
|
||||||
@ -103,7 +117,7 @@ LL + &[_, _, ..] => todo!()
|
|||||||
|
|
|
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
|
error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
|
||||||
--> $DIR/slice-patterns-exhaustiveness.rs:51:11
|
--> $DIR/slice-patterns-exhaustiveness.rs:55:11
|
||||||
|
|
|
|
||||||
LL | match s {
|
LL | match s {
|
||||||
| ^ pattern `&[false, ..]` not covered
|
| ^ pattern `&[false, ..]` not covered
|
||||||
@ -116,7 +130,7 @@ LL + &[false, ..] => todo!()
|
|||||||
|
|
|
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `&[false, _, ..]` not covered
|
error[E0004]: non-exhaustive patterns: `&[false, _, ..]` not covered
|
||||||
--> $DIR/slice-patterns-exhaustiveness.rs:56:11
|
--> $DIR/slice-patterns-exhaustiveness.rs:60:11
|
||||||
|
|
|
|
||||||
LL | match s {
|
LL | match s {
|
||||||
| ^ pattern `&[false, _, ..]` not covered
|
| ^ pattern `&[false, _, ..]` not covered
|
||||||
@ -129,7 +143,7 @@ LL + &[false, _, ..] => todo!()
|
|||||||
|
|
|
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `&[_, .., false]` not covered
|
error[E0004]: non-exhaustive patterns: `&[_, .., false]` not covered
|
||||||
--> $DIR/slice-patterns-exhaustiveness.rs:62:11
|
--> $DIR/slice-patterns-exhaustiveness.rs:66:11
|
||||||
|
|
|
|
||||||
LL | match s {
|
LL | match s {
|
||||||
| ^ pattern `&[_, .., false]` not covered
|
| ^ pattern `&[_, .., false]` not covered
|
||||||
@ -142,7 +156,7 @@ LL + &[_, .., false] => todo!()
|
|||||||
|
|
|
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `&[_, _, .., true]` not covered
|
error[E0004]: non-exhaustive patterns: `&[_, _, .., true]` not covered
|
||||||
--> $DIR/slice-patterns-exhaustiveness.rs:69:11
|
--> $DIR/slice-patterns-exhaustiveness.rs:73:11
|
||||||
|
|
|
|
||||||
LL | match s {
|
LL | match s {
|
||||||
| ^ pattern `&[_, _, .., true]` not covered
|
| ^ pattern `&[_, _, .., true]` not covered
|
||||||
@ -155,7 +169,7 @@ LL + &[_, _, .., true] => todo!()
|
|||||||
|
|
|
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `&[true, _, .., _]` not covered
|
error[E0004]: non-exhaustive patterns: `&[true, _, .., _]` not covered
|
||||||
--> $DIR/slice-patterns-exhaustiveness.rs:76:11
|
--> $DIR/slice-patterns-exhaustiveness.rs:80:11
|
||||||
|
|
|
|
||||||
LL | match s {
|
LL | match s {
|
||||||
| ^ pattern `&[true, _, .., _]` not covered
|
| ^ pattern `&[true, _, .., _]` not covered
|
||||||
@ -168,7 +182,7 @@ LL + &[true, _, .., _] => todo!()
|
|||||||
|
|
|
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
|
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
|
||||||
--> $DIR/slice-patterns-exhaustiveness.rs:85:11
|
--> $DIR/slice-patterns-exhaustiveness.rs:89:11
|
||||||
|
|
|
|
||||||
LL | match s {
|
LL | match s {
|
||||||
| ^ patterns `&[]` and `&[_, _, ..]` not covered
|
| ^ patterns `&[]` and `&[_, _, ..]` not covered
|
||||||
@ -181,7 +195,7 @@ LL + &[] | &[_, _, ..] => todo!()
|
|||||||
|
|
|
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
|
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
|
||||||
--> $DIR/slice-patterns-exhaustiveness.rs:89:11
|
--> $DIR/slice-patterns-exhaustiveness.rs:93:11
|
||||||
|
|
|
|
||||||
LL | match s {
|
LL | match s {
|
||||||
| ^ patterns `&[]` and `&[_, _, ..]` not covered
|
| ^ patterns `&[]` and `&[_, _, ..]` not covered
|
||||||
@ -194,7 +208,7 @@ LL + &[] | &[_, _, ..] => todo!()
|
|||||||
|
|
|
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
|
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
|
||||||
--> $DIR/slice-patterns-exhaustiveness.rs:93:11
|
--> $DIR/slice-patterns-exhaustiveness.rs:97:11
|
||||||
|
|
|
|
||||||
LL | match s {
|
LL | match s {
|
||||||
| ^ patterns `&[]` and `&[_, _, ..]` not covered
|
| ^ patterns `&[]` and `&[_, _, ..]` not covered
|
||||||
@ -207,7 +221,7 @@ LL + &[] | &[_, _, ..] => todo!()
|
|||||||
|
|
|
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
|
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
|
||||||
--> $DIR/slice-patterns-exhaustiveness.rs:98:11
|
--> $DIR/slice-patterns-exhaustiveness.rs:102:11
|
||||||
|
|
|
|
||||||
LL | match s {
|
LL | match s {
|
||||||
| ^ patterns `&[]` and `&[_, _, ..]` not covered
|
| ^ patterns `&[]` and `&[_, _, ..]` not covered
|
||||||
@ -220,7 +234,7 @@ LL + &[] | &[_, _, ..] => todo!()
|
|||||||
|
|
|
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered
|
error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered
|
||||||
--> $DIR/slice-patterns-exhaustiveness.rs:103:11
|
--> $DIR/slice-patterns-exhaustiveness.rs:107:11
|
||||||
|
|
|
|
||||||
LL | match s {
|
LL | match s {
|
||||||
| ^ pattern `&[_, _, ..]` not covered
|
| ^ pattern `&[_, _, ..]` not covered
|
||||||
@ -233,7 +247,7 @@ LL + &[_, _, ..] => todo!()
|
|||||||
|
|
|
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `&[false]` not covered
|
error[E0004]: non-exhaustive patterns: `&[false]` not covered
|
||||||
--> $DIR/slice-patterns-exhaustiveness.rs:108:11
|
--> $DIR/slice-patterns-exhaustiveness.rs:112:11
|
||||||
|
|
|
|
||||||
LL | match s {
|
LL | match s {
|
||||||
| ^ pattern `&[false]` not covered
|
| ^ pattern `&[false]` not covered
|
||||||
@ -246,7 +260,7 @@ LL + &[false] => todo!()
|
|||||||
|
|
|
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `&[false]` not covered
|
error[E0004]: non-exhaustive patterns: `&[false]` not covered
|
||||||
--> $DIR/slice-patterns-exhaustiveness.rs:121:11
|
--> $DIR/slice-patterns-exhaustiveness.rs:125:11
|
||||||
|
|
|
|
||||||
LL | match s1 {
|
LL | match s1 {
|
||||||
| ^^ pattern `&[false]` not covered
|
| ^^ pattern `&[false]` not covered
|
||||||
@ -258,6 +272,6 @@ LL ~ CONST1 => {},
|
|||||||
LL + &[false] => todo!()
|
LL + &[false] => todo!()
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 20 previous errors
|
error: aborting due to 21 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0004`.
|
For more information about this error, try `rustc --explain E0004`.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Test that the `non_exhaustive_omitted_patterns` lint is triggered correctly.
|
// Test that the `non_exhaustive_omitted_patterns` lint is triggered correctly.
|
||||||
|
|
||||||
#![feature(non_exhaustive_omitted_patterns_lint, unstable_test_feature)]
|
#![feature(non_exhaustive_omitted_patterns_lint, unstable_test_feature)]
|
||||||
|
#![deny(unreachable_patterns)]
|
||||||
|
|
||||||
// aux-build:enums.rs
|
// aux-build:enums.rs
|
||||||
extern crate enums;
|
extern crate enums;
|
||||||
@ -31,11 +32,21 @@ pub enum Bar {
|
|||||||
C,
|
C,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn no_lint() {
|
||||||
|
let non_enum = NonExhaustiveEnum::Unit;
|
||||||
|
// Ok: without the attribute
|
||||||
|
match non_enum {
|
||||||
|
NonExhaustiveEnum::Unit => {}
|
||||||
|
NonExhaustiveEnum::Tuple(_) => {}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deny(non_exhaustive_omitted_patterns)]
|
||||||
fn main() {
|
fn main() {
|
||||||
let enumeration = Bar::A;
|
let enumeration = Bar::A;
|
||||||
|
|
||||||
// Ok: this is a crate local non_exhaustive enum
|
// Ok: this is a crate local non_exhaustive enum
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
match enumeration {
|
match enumeration {
|
||||||
Bar::A => {}
|
Bar::A => {}
|
||||||
Bar::B => {}
|
Bar::B => {}
|
||||||
@ -44,14 +55,13 @@ fn main() {
|
|||||||
|
|
||||||
let non_enum = NonExhaustiveEnum::Unit;
|
let non_enum = NonExhaustiveEnum::Unit;
|
||||||
|
|
||||||
// Ok: without the attribute
|
#[allow(non_exhaustive_omitted_patterns)]
|
||||||
match non_enum {
|
match non_enum {
|
||||||
NonExhaustiveEnum::Unit => {}
|
NonExhaustiveEnum::Unit => {}
|
||||||
NonExhaustiveEnum::Tuple(_) => {}
|
NonExhaustiveEnum::Tuple(_) => {}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
match non_enum {
|
match non_enum {
|
||||||
//~^ some variants are not matched explicitly
|
//~^ some variants are not matched explicitly
|
||||||
NonExhaustiveEnum::Unit => {}
|
NonExhaustiveEnum::Unit => {}
|
||||||
@ -59,7 +69,6 @@ fn main() {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
match non_enum {
|
match non_enum {
|
||||||
//~^ some variants are not matched explicitly
|
//~^ some variants are not matched explicitly
|
||||||
NonExhaustiveEnum::Unit | NonExhaustiveEnum::Struct { .. } => {}
|
NonExhaustiveEnum::Unit | NonExhaustiveEnum::Struct { .. } => {}
|
||||||
@ -68,7 +77,6 @@ fn main() {
|
|||||||
|
|
||||||
let x = 5;
|
let x = 5;
|
||||||
// We ignore the guard.
|
// We ignore the guard.
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
match non_enum {
|
match non_enum {
|
||||||
NonExhaustiveEnum::Unit if x > 10 => {}
|
NonExhaustiveEnum::Unit if x > 10 => {}
|
||||||
NonExhaustiveEnum::Tuple(_) => {}
|
NonExhaustiveEnum::Tuple(_) => {}
|
||||||
@ -76,14 +84,12 @@ fn main() {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
match (non_enum, true) {
|
match (non_enum, true) {
|
||||||
(NonExhaustiveEnum::Unit, true) => {}
|
(NonExhaustiveEnum::Unit, true) => {}
|
||||||
(NonExhaustiveEnum::Tuple(_), false) => {}
|
(NonExhaustiveEnum::Tuple(_), false) => {}
|
||||||
(NonExhaustiveEnum::Struct { .. }, false) => {}
|
(NonExhaustiveEnum::Struct { .. }, false) => {}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
match (non_enum, true) {
|
match (non_enum, true) {
|
||||||
//~^ some variants are not matched explicitly
|
//~^ some variants are not matched explicitly
|
||||||
(NonExhaustiveEnum::Unit, true) => {}
|
(NonExhaustiveEnum::Unit, true) => {}
|
||||||
@ -91,14 +97,12 @@ fn main() {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
match (true, non_enum) {
|
match (true, non_enum) {
|
||||||
(true, NonExhaustiveEnum::Unit) => {}
|
(true, NonExhaustiveEnum::Unit) => {}
|
||||||
(false, NonExhaustiveEnum::Tuple(_)) => {}
|
(false, NonExhaustiveEnum::Tuple(_)) => {}
|
||||||
(false, NonExhaustiveEnum::Struct { .. }) => {}
|
(false, NonExhaustiveEnum::Struct { .. }) => {}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
match (true, non_enum) {
|
match (true, non_enum) {
|
||||||
//~^ some variants are not matched explicitly
|
//~^ some variants are not matched explicitly
|
||||||
(true, NonExhaustiveEnum::Unit) => {}
|
(true, NonExhaustiveEnum::Unit) => {}
|
||||||
@ -106,7 +110,6 @@ fn main() {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
match Some(non_enum) {
|
match Some(non_enum) {
|
||||||
//~^ some variants are not matched explicitly
|
//~^ some variants are not matched explicitly
|
||||||
Some(NonExhaustiveEnum::Unit) => {}
|
Some(NonExhaustiveEnum::Unit) => {}
|
||||||
@ -116,7 +119,6 @@ fn main() {
|
|||||||
|
|
||||||
// Ok: all covered and not `unreachable-patterns`
|
// Ok: all covered and not `unreachable-patterns`
|
||||||
#[deny(unreachable_patterns)]
|
#[deny(unreachable_patterns)]
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
match non_enum {
|
match non_enum {
|
||||||
NonExhaustiveEnum::Unit => {}
|
NonExhaustiveEnum::Unit => {}
|
||||||
NonExhaustiveEnum::Tuple(_) => {}
|
NonExhaustiveEnum::Tuple(_) => {}
|
||||||
@ -124,7 +126,6 @@ fn main() {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
match NestedNonExhaustive::B {
|
match NestedNonExhaustive::B {
|
||||||
//~^ some variants are not matched explicitly
|
//~^ some variants are not matched explicitly
|
||||||
NestedNonExhaustive::A(NonExhaustiveEnum::Unit) => {}
|
NestedNonExhaustive::A(NonExhaustiveEnum::Unit) => {}
|
||||||
@ -133,54 +134,53 @@ fn main() {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[warn(non_exhaustive_omitted_patterns)]
|
|
||||||
match VariantNonExhaustive::Baz(1, 2) {
|
match VariantNonExhaustive::Baz(1, 2) {
|
||||||
VariantNonExhaustive::Baz(_, _) => {}
|
VariantNonExhaustive::Baz(_, _) => {}
|
||||||
VariantNonExhaustive::Bar { x, .. } => {}
|
VariantNonExhaustive::Bar { x, .. } => {}
|
||||||
}
|
}
|
||||||
//~^^ some fields are not explicitly listed
|
//~^^ some fields are not explicitly listed
|
||||||
|
|
||||||
#[warn(non_exhaustive_omitted_patterns)]
|
|
||||||
let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default();
|
let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default();
|
||||||
//~^ some fields are not explicitly listed
|
//~^ some fields are not explicitly listed
|
||||||
|
|
||||||
// Ok: this is local
|
// Ok: this is local
|
||||||
#[warn(non_exhaustive_omitted_patterns)]
|
|
||||||
let Foo { a, b, .. } = Foo::default();
|
let Foo { a, b, .. } = Foo::default();
|
||||||
|
|
||||||
#[warn(non_exhaustive_omitted_patterns)]
|
|
||||||
let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
|
let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
|
||||||
//~^ some fields are not explicitly listed
|
//~^ some fields are not explicitly listed
|
||||||
//~^^ some fields are not explicitly listed
|
//~^^ some fields are not explicitly listed
|
||||||
|
|
||||||
// Ok: this tests https://github.com/rust-lang/rust/issues/89382
|
// Ok: this tests https://github.com/rust-lang/rust/issues/89382
|
||||||
#[warn(non_exhaustive_omitted_patterns)]
|
|
||||||
let MixedVisFields { a, b, .. } = MixedVisFields::default();
|
let MixedVisFields { a, b, .. } = MixedVisFields::default();
|
||||||
|
|
||||||
// Ok: this only has 1 variant
|
// Ok: this only has 1 variant
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
match NonExhaustiveSingleVariant::A(true) {
|
match NonExhaustiveSingleVariant::A(true) {
|
||||||
NonExhaustiveSingleVariant::A(true) => {}
|
NonExhaustiveSingleVariant::A(true) => {}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can't catch the case below, so for consistency we don't catch this one either.
|
// We can't catch the case below, so for consistency we don't catch this one either.
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
match NonExhaustiveSingleVariant::A(true) {
|
match NonExhaustiveSingleVariant::A(true) {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
// We can't catch this case, because this would require digging fully through all the values of
|
// We can't catch this case, because this would require digging fully through all the values of
|
||||||
// any type we encounter. We need to be able to only consider present constructors.
|
// any type we encounter. We need to be able to only consider present constructors.
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
match &NonExhaustiveSingleVariant::A(true) {
|
match &NonExhaustiveSingleVariant::A(true) {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match Some(NonExhaustiveSingleVariant::A(true)) {
|
||||||
|
Some(_) => {}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
match Some(&NonExhaustiveSingleVariant::A(true)) {
|
||||||
|
Some(_) => {}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
|
||||||
// Ok: we don't lint on `if let` expressions
|
// Ok: we don't lint on `if let` expressions
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
if let NonExhaustiveEnum::Tuple(_) = non_enum {}
|
if let NonExhaustiveEnum::Tuple(_) = non_enum {}
|
||||||
|
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
match UnstableEnum::Stable {
|
match UnstableEnum::Stable {
|
||||||
//~^ some variants are not matched explicitly
|
//~^ some variants are not matched explicitly
|
||||||
UnstableEnum::Stable => {}
|
UnstableEnum::Stable => {}
|
||||||
@ -189,7 +189,6 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ok: the feature is on and all variants are matched
|
// Ok: the feature is on and all variants are matched
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
match UnstableEnum::Stable {
|
match UnstableEnum::Stable {
|
||||||
UnstableEnum::Stable => {}
|
UnstableEnum::Stable => {}
|
||||||
UnstableEnum::Stable2 => {}
|
UnstableEnum::Stable2 => {}
|
||||||
@ -198,52 +197,66 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ok: the feature is on and both variants are matched
|
// Ok: the feature is on and both variants are matched
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
match OnlyUnstableEnum::Unstable {
|
match OnlyUnstableEnum::Unstable {
|
||||||
OnlyUnstableEnum::Unstable => {}
|
OnlyUnstableEnum::Unstable => {}
|
||||||
OnlyUnstableEnum::Unstable2 => {}
|
OnlyUnstableEnum::Unstable2 => {}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
match OnlyUnstableEnum::Unstable {
|
match OnlyUnstableEnum::Unstable {
|
||||||
//~^ some variants are not matched explicitly
|
//~^ some variants are not matched explicitly
|
||||||
OnlyUnstableEnum::Unstable => {}
|
OnlyUnstableEnum::Unstable => {}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[warn(non_exhaustive_omitted_patterns)]
|
|
||||||
let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new();
|
let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new();
|
||||||
//~^ some fields are not explicitly listed
|
//~^ some fields are not explicitly listed
|
||||||
|
|
||||||
// OK: both unstable fields are matched with feature on
|
// OK: both unstable fields are matched with feature on
|
||||||
#[warn(non_exhaustive_omitted_patterns)]
|
|
||||||
let OnlyUnstableStruct { unstable, unstable2, .. } = OnlyUnstableStruct::new();
|
let OnlyUnstableStruct { unstable, unstable2, .. } = OnlyUnstableStruct::new();
|
||||||
|
|
||||||
#[warn(non_exhaustive_omitted_patterns)]
|
|
||||||
let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
|
let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
|
||||||
//~^ some fields are not explicitly listed
|
//~^ some fields are not explicitly listed
|
||||||
|
|
||||||
// OK: both unstable and stable fields are matched with feature on
|
// OK: both unstable and stable fields are matched with feature on
|
||||||
#[warn(non_exhaustive_omitted_patterns)]
|
|
||||||
let UnstableStruct { stable, stable2, unstable, .. } = UnstableStruct::default();
|
let UnstableStruct { stable, stable2, unstable, .. } = UnstableStruct::default();
|
||||||
|
|
||||||
// Ok: local bindings are allowed
|
// Ok: local bindings are allowed
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
let local = NonExhaustiveEnum::Unit;
|
let local = NonExhaustiveEnum::Unit;
|
||||||
|
|
||||||
// Ok: missing patterns will be blocked by the pattern being refutable
|
// Ok: missing patterns will be blocked by the pattern being refutable
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit;
|
let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit;
|
||||||
//~^ refutable pattern in local binding
|
//~^ refutable pattern in local binding
|
||||||
|
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
// Check that matching on a reference results in a correct diagnostic
|
||||||
match &non_enum {
|
match &non_enum {
|
||||||
//~^ some variants are not matched explicitly
|
//~^ some variants are not matched explicitly
|
||||||
|
//~| pattern `&NonExhaustiveEnum::Struct { .. }` not covered
|
||||||
NonExhaustiveEnum::Unit => {}
|
NonExhaustiveEnum::Unit => {}
|
||||||
NonExhaustiveEnum::Tuple(_) => {}
|
NonExhaustiveEnum::Tuple(_) => {}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match (true, &non_enum) {
|
||||||
|
//~^ some variants are not matched explicitly
|
||||||
|
//~| patterns `(_, &NonExhaustiveEnum::Tuple(_))` and `(_, &NonExhaustiveEnum::Struct { .. })` not covered
|
||||||
|
(true, NonExhaustiveEnum::Unit) => {}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
match (&non_enum, true) {
|
||||||
|
//~^ some variants are not matched explicitly
|
||||||
|
//~| patterns `(&NonExhaustiveEnum::Tuple(_), _)` and `(&NonExhaustiveEnum::Struct { .. }, _)` not covered
|
||||||
|
(NonExhaustiveEnum::Unit, true) => {}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
match Some(&non_enum) {
|
||||||
|
//~^ some variants are not matched explicitly
|
||||||
|
//~| pattern `Some(&NonExhaustiveEnum::Struct { .. })` not covered
|
||||||
|
Some(NonExhaustiveEnum::Unit | NonExhaustiveEnum::Tuple(_)) => {}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
#[deny(non_exhaustive_omitted_patterns)]
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
warning: some fields are not explicitly listed
|
error: some fields are not explicitly listed
|
||||||
--> $DIR/omitted-patterns.rs:139:9
|
--> $DIR/omitted-patterns.rs:139:9
|
||||||
|
|
|
|
||||||
LL | VariantNonExhaustive::Bar { x, .. } => {}
|
LL | VariantNonExhaustive::Bar { x, .. } => {}
|
||||||
@ -7,41 +7,31 @@ LL | VariantNonExhaustive::Bar { x, .. } => {}
|
|||||||
= help: ensure that all fields are mentioned explicitly by adding the suggested fields
|
= help: ensure that all fields are mentioned explicitly by adding the suggested fields
|
||||||
= note: the pattern is of type `VariantNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found
|
= note: the pattern is of type `VariantNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/omitted-patterns.rs:136:12
|
--> $DIR/omitted-patterns.rs:45:8
|
||||||
|
|
|
|
||||||
LL | #[warn(non_exhaustive_omitted_patterns)]
|
LL | #[deny(non_exhaustive_omitted_patterns)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
warning: some fields are not explicitly listed
|
error: some fields are not explicitly listed
|
||||||
--> $DIR/omitted-patterns.rs:144:9
|
--> $DIR/omitted-patterns.rs:143:9
|
||||||
|
|
|
|
||||||
LL | let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default();
|
LL | let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `third_field` not listed
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `third_field` not listed
|
||||||
|
|
|
|
||||||
= help: ensure that all fields are mentioned explicitly by adding the suggested fields
|
= help: ensure that all fields are mentioned explicitly by adding the suggested fields
|
||||||
= note: the pattern is of type `FunctionalRecord` and the `non_exhaustive_omitted_patterns` attribute was found
|
= note: the pattern is of type `FunctionalRecord` and the `non_exhaustive_omitted_patterns` attribute was found
|
||||||
note: the lint level is defined here
|
|
||||||
--> $DIR/omitted-patterns.rs:143:12
|
|
||||||
|
|
|
||||||
LL | #[warn(non_exhaustive_omitted_patterns)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
warning: some fields are not explicitly listed
|
error: some fields are not explicitly listed
|
||||||
--> $DIR/omitted-patterns.rs:152:29
|
--> $DIR/omitted-patterns.rs:149:29
|
||||||
|
|
|
|
||||||
LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
|
LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `second_field` not listed
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `second_field` not listed
|
||||||
|
|
|
|
||||||
= help: ensure that all fields are mentioned explicitly by adding the suggested fields
|
= help: ensure that all fields are mentioned explicitly by adding the suggested fields
|
||||||
= note: the pattern is of type `NormalStruct` and the `non_exhaustive_omitted_patterns` attribute was found
|
= note: the pattern is of type `NormalStruct` and the `non_exhaustive_omitted_patterns` attribute was found
|
||||||
note: the lint level is defined here
|
|
||||||
--> $DIR/omitted-patterns.rs:151:12
|
|
||||||
|
|
|
||||||
LL | #[warn(non_exhaustive_omitted_patterns)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
warning: some fields are not explicitly listed
|
error: some fields are not explicitly listed
|
||||||
--> $DIR/omitted-patterns.rs:152:9
|
--> $DIR/omitted-patterns.rs:149:9
|
||||||
|
|
|
|
||||||
LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
|
LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `foo` not listed
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `foo` not listed
|
||||||
@ -49,117 +39,77 @@ LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = Nested
|
|||||||
= help: ensure that all fields are mentioned explicitly by adding the suggested fields
|
= help: ensure that all fields are mentioned explicitly by adding the suggested fields
|
||||||
= note: the pattern is of type `NestedStruct` and the `non_exhaustive_omitted_patterns` attribute was found
|
= note: the pattern is of type `NestedStruct` and the `non_exhaustive_omitted_patterns` attribute was found
|
||||||
|
|
||||||
warning: some fields are not explicitly listed
|
error: some fields are not explicitly listed
|
||||||
--> $DIR/omitted-patterns.rs:216:9
|
--> $DIR/omitted-patterns.rs:212:9
|
||||||
|
|
|
|
||||||
LL | let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new();
|
LL | let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `unstable2` not listed
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `unstable2` not listed
|
||||||
|
|
|
|
||||||
= help: ensure that all fields are mentioned explicitly by adding the suggested fields
|
= help: ensure that all fields are mentioned explicitly by adding the suggested fields
|
||||||
= note: the pattern is of type `OnlyUnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found
|
= note: the pattern is of type `OnlyUnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found
|
||||||
note: the lint level is defined here
|
|
||||||
--> $DIR/omitted-patterns.rs:215:12
|
|
||||||
|
|
|
||||||
LL | #[warn(non_exhaustive_omitted_patterns)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
warning: some fields are not explicitly listed
|
error: some fields are not explicitly listed
|
||||||
--> $DIR/omitted-patterns.rs:224:9
|
--> $DIR/omitted-patterns.rs:218:9
|
||||||
|
|
|
|
||||||
LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
|
LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `unstable` not listed
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `unstable` not listed
|
||||||
|
|
|
|
||||||
= help: ensure that all fields are mentioned explicitly by adding the suggested fields
|
= help: ensure that all fields are mentioned explicitly by adding the suggested fields
|
||||||
= note: the pattern is of type `UnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found
|
= note: the pattern is of type `UnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found
|
||||||
note: the lint level is defined here
|
|
||||||
--> $DIR/omitted-patterns.rs:223:12
|
|
||||||
|
|
|
||||||
LL | #[warn(non_exhaustive_omitted_patterns)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: some variants are not matched explicitly
|
error: some variants are not matched explicitly
|
||||||
--> $DIR/omitted-patterns.rs:55:11
|
--> $DIR/omitted-patterns.rs:65:11
|
||||||
|
|
|
|
||||||
LL | match non_enum {
|
LL | match non_enum {
|
||||||
| ^^^^^^^^ pattern `NonExhaustiveEnum::Struct { .. }` not covered
|
| ^^^^^^^^ pattern `NonExhaustiveEnum::Struct { .. }` not covered
|
||||||
|
|
|
|
||||||
= help: ensure that all variants are matched explicitly by adding the suggested match arms
|
= help: ensure that all variants are matched explicitly by adding the suggested match arms
|
||||||
= note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
|
= note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
|
||||||
note: the lint level is defined here
|
|
||||||
--> $DIR/omitted-patterns.rs:54:12
|
|
||||||
|
|
|
||||||
LL | #[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: some variants are not matched explicitly
|
error: some variants are not matched explicitly
|
||||||
--> $DIR/omitted-patterns.rs:63:11
|
--> $DIR/omitted-patterns.rs:72:11
|
||||||
|
|
|
|
||||||
LL | match non_enum {
|
LL | match non_enum {
|
||||||
| ^^^^^^^^ pattern `NonExhaustiveEnum::Tuple(_)` not covered
|
| ^^^^^^^^ pattern `NonExhaustiveEnum::Tuple(_)` not covered
|
||||||
|
|
|
|
||||||
= help: ensure that all variants are matched explicitly by adding the suggested match arms
|
= help: ensure that all variants are matched explicitly by adding the suggested match arms
|
||||||
= note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
|
= note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
|
||||||
note: the lint level is defined here
|
|
||||||
--> $DIR/omitted-patterns.rs:62:12
|
|
||||||
|
|
|
||||||
LL | #[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: some variants are not matched explicitly
|
error: some variants are not matched explicitly
|
||||||
--> $DIR/omitted-patterns.rs:87:11
|
--> $DIR/omitted-patterns.rs:93:11
|
||||||
|
|
|
|
||||||
LL | match (non_enum, true) {
|
LL | match (non_enum, true) {
|
||||||
| ^^^^^^^^^^^^^^^^ pattern `(NonExhaustiveEnum::Struct { .. }, _)` not covered
|
| ^^^^^^^^^^^^^^^^ pattern `(NonExhaustiveEnum::Struct { .. }, _)` not covered
|
||||||
|
|
|
|
||||||
= help: ensure that all variants are matched explicitly by adding the suggested match arms
|
= help: ensure that all variants are matched explicitly by adding the suggested match arms
|
||||||
= note: the matched value is of type `(NonExhaustiveEnum, bool)` and the `non_exhaustive_omitted_patterns` attribute was found
|
= note: the matched value is of type `(NonExhaustiveEnum, bool)` and the `non_exhaustive_omitted_patterns` attribute was found
|
||||||
note: the lint level is defined here
|
|
||||||
--> $DIR/omitted-patterns.rs:86:12
|
|
||||||
|
|
|
||||||
LL | #[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: some variants are not matched explicitly
|
error: some variants are not matched explicitly
|
||||||
--> $DIR/omitted-patterns.rs:102:11
|
--> $DIR/omitted-patterns.rs:106:11
|
||||||
|
|
|
|
||||||
LL | match (true, non_enum) {
|
LL | match (true, non_enum) {
|
||||||
| ^^^^^^^^^^^^^^^^ pattern `(_, NonExhaustiveEnum::Struct { .. })` not covered
|
| ^^^^^^^^^^^^^^^^ pattern `(_, NonExhaustiveEnum::Struct { .. })` not covered
|
||||||
|
|
|
|
||||||
= help: ensure that all variants are matched explicitly by adding the suggested match arms
|
= help: ensure that all variants are matched explicitly by adding the suggested match arms
|
||||||
= note: the matched value is of type `(bool, NonExhaustiveEnum)` and the `non_exhaustive_omitted_patterns` attribute was found
|
= note: the matched value is of type `(bool, NonExhaustiveEnum)` and the `non_exhaustive_omitted_patterns` attribute was found
|
||||||
note: the lint level is defined here
|
|
||||||
--> $DIR/omitted-patterns.rs:101:12
|
|
||||||
|
|
|
||||||
LL | #[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: some variants are not matched explicitly
|
error: some variants are not matched explicitly
|
||||||
--> $DIR/omitted-patterns.rs:110:11
|
--> $DIR/omitted-patterns.rs:113:11
|
||||||
|
|
|
|
||||||
LL | match Some(non_enum) {
|
LL | match Some(non_enum) {
|
||||||
| ^^^^^^^^^^^^^^ pattern `Some(NonExhaustiveEnum::Struct { .. })` not covered
|
| ^^^^^^^^^^^^^^ pattern `Some(NonExhaustiveEnum::Struct { .. })` not covered
|
||||||
|
|
|
|
||||||
= help: ensure that all variants are matched explicitly by adding the suggested match arms
|
= help: ensure that all variants are matched explicitly by adding the suggested match arms
|
||||||
= note: the matched value is of type `Option<NonExhaustiveEnum>` and the `non_exhaustive_omitted_patterns` attribute was found
|
= note: the matched value is of type `Option<NonExhaustiveEnum>` and the `non_exhaustive_omitted_patterns` attribute was found
|
||||||
note: the lint level is defined here
|
|
||||||
--> $DIR/omitted-patterns.rs:109:12
|
|
||||||
|
|
|
||||||
LL | #[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: some variants are not matched explicitly
|
error: some variants are not matched explicitly
|
||||||
--> $DIR/omitted-patterns.rs:128:11
|
--> $DIR/omitted-patterns.rs:129:11
|
||||||
|
|
|
|
||||||
LL | match NestedNonExhaustive::B {
|
LL | match NestedNonExhaustive::B {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^ patterns `NestedNonExhaustive::C`, `NestedNonExhaustive::A(NonExhaustiveEnum::Tuple(_))` and `NestedNonExhaustive::A(NonExhaustiveEnum::Struct { .. })` not covered
|
| ^^^^^^^^^^^^^^^^^^^^^^ patterns `NestedNonExhaustive::C`, `NestedNonExhaustive::A(NonExhaustiveEnum::Tuple(_))` and `NestedNonExhaustive::A(NonExhaustiveEnum::Struct { .. })` not covered
|
||||||
|
|
|
|
||||||
= help: ensure that all variants are matched explicitly by adding the suggested match arms
|
= help: ensure that all variants are matched explicitly by adding the suggested match arms
|
||||||
= note: the matched value is of type `NestedNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found
|
= note: the matched value is of type `NestedNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found
|
||||||
note: the lint level is defined here
|
|
||||||
--> $DIR/omitted-patterns.rs:127:12
|
|
||||||
|
|
|
||||||
LL | #[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: some variants are not matched explicitly
|
error: some variants are not matched explicitly
|
||||||
--> $DIR/omitted-patterns.rs:184:11
|
--> $DIR/omitted-patterns.rs:184:11
|
||||||
@ -169,28 +119,18 @@ LL | match UnstableEnum::Stable {
|
|||||||
|
|
|
|
||||||
= help: ensure that all variants are matched explicitly by adding the suggested match arms
|
= help: ensure that all variants are matched explicitly by adding the suggested match arms
|
||||||
= note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
|
= note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
|
||||||
note: the lint level is defined here
|
|
||||||
--> $DIR/omitted-patterns.rs:183:12
|
|
||||||
|
|
|
||||||
LL | #[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: some variants are not matched explicitly
|
error: some variants are not matched explicitly
|
||||||
--> $DIR/omitted-patterns.rs:209:11
|
--> $DIR/omitted-patterns.rs:206:11
|
||||||
|
|
|
|
||||||
LL | match OnlyUnstableEnum::Unstable {
|
LL | match OnlyUnstableEnum::Unstable {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `OnlyUnstableEnum::Unstable2` not covered
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `OnlyUnstableEnum::Unstable2` not covered
|
||||||
|
|
|
|
||||||
= help: ensure that all variants are matched explicitly by adding the suggested match arms
|
= help: ensure that all variants are matched explicitly by adding the suggested match arms
|
||||||
= note: the matched value is of type `OnlyUnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
|
= note: the matched value is of type `OnlyUnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
|
||||||
note: the lint level is defined here
|
|
||||||
--> $DIR/omitted-patterns.rs:208:12
|
|
||||||
|
|
|
||||||
LL | #[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error[E0005]: refutable pattern in local binding
|
error[E0005]: refutable pattern in local binding
|
||||||
--> $DIR/omitted-patterns.rs:237:9
|
--> $DIR/omitted-patterns.rs:228:9
|
||||||
|
|
|
|
||||||
LL | let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit;
|
LL | let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit;
|
||||||
| ^^^^^^^^^^^^^^^ pattern `_` not covered
|
| ^^^^^^^^^^^^^^^ pattern `_` not covered
|
||||||
@ -204,19 +144,41 @@ LL | let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit
|
|||||||
| ++++++++++++++++
|
| ++++++++++++++++
|
||||||
|
|
||||||
error: some variants are not matched explicitly
|
error: some variants are not matched explicitly
|
||||||
--> $DIR/omitted-patterns.rs:241:11
|
--> $DIR/omitted-patterns.rs:232:11
|
||||||
|
|
|
|
||||||
LL | match &non_enum {
|
LL | match &non_enum {
|
||||||
| ^^^^^^^^^ pattern `&NonExhaustiveEnum::Struct { .. }` not covered
|
| ^^^^^^^^^ pattern `&NonExhaustiveEnum::Struct { .. }` not covered
|
||||||
|
|
|
|
||||||
= help: ensure that all variants are matched explicitly by adding the suggested match arms
|
= help: ensure that all variants are matched explicitly by adding the suggested match arms
|
||||||
= note: the matched value is of type `&NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
|
= note: the matched value is of type `&NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
|
||||||
note: the lint level is defined here
|
|
||||||
--> $DIR/omitted-patterns.rs:240:12
|
|
||||||
|
|
|
||||||
LL | #[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to 10 previous errors; 6 warnings emitted
|
error: some variants are not matched explicitly
|
||||||
|
--> $DIR/omitted-patterns.rs:240:11
|
||||||
|
|
|
||||||
|
LL | match (true, &non_enum) {
|
||||||
|
| ^^^^^^^^^^^^^^^^^ patterns `(_, &NonExhaustiveEnum::Tuple(_))` and `(_, &NonExhaustiveEnum::Struct { .. })` not covered
|
||||||
|
|
|
||||||
|
= help: ensure that all variants are matched explicitly by adding the suggested match arms
|
||||||
|
= note: the matched value is of type `(bool, &NonExhaustiveEnum)` and the `non_exhaustive_omitted_patterns` attribute was found
|
||||||
|
|
||||||
|
error: some variants are not matched explicitly
|
||||||
|
--> $DIR/omitted-patterns.rs:247:11
|
||||||
|
|
|
||||||
|
LL | match (&non_enum, true) {
|
||||||
|
| ^^^^^^^^^^^^^^^^^ patterns `(&NonExhaustiveEnum::Tuple(_), _)` and `(&NonExhaustiveEnum::Struct { .. }, _)` not covered
|
||||||
|
|
|
||||||
|
= help: ensure that all variants are matched explicitly by adding the suggested match arms
|
||||||
|
= note: the matched value is of type `(&NonExhaustiveEnum, bool)` and the `non_exhaustive_omitted_patterns` attribute was found
|
||||||
|
|
||||||
|
error: some variants are not matched explicitly
|
||||||
|
--> $DIR/omitted-patterns.rs:254:11
|
||||||
|
|
|
||||||
|
LL | match Some(&non_enum) {
|
||||||
|
| ^^^^^^^^^^^^^^^ pattern `Some(&NonExhaustiveEnum::Struct { .. })` not covered
|
||||||
|
|
|
||||||
|
= help: ensure that all variants are matched explicitly by adding the suggested match arms
|
||||||
|
= note: the matched value is of type `Option<&NonExhaustiveEnum>` and the `non_exhaustive_omitted_patterns` attribute was found
|
||||||
|
|
||||||
|
error: aborting due to 19 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0005`.
|
For more information about this error, try `rustc --explain E0005`.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user