Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 57cc6aa

Browse files
committedOct 21, 2023
Match usize/isize exhaustively
1 parent 291ee39 commit 57cc6aa

18 files changed

+323
-306
lines changed
 

‎compiler/rustc_mir_build/src/thir/pattern/check_match.rs

+21-6
Original file line numberDiff line numberDiff line change
@@ -703,14 +703,21 @@ fn report_arm_reachability<'p, 'tcx>(
703703
}
704704

705705
fn collect_non_exhaustive_tys<'tcx>(
706+
tcx: TyCtxt<'tcx>,
706707
pat: &WitnessPat<'tcx>,
707708
non_exhaustive_tys: &mut FxHashSet<Ty<'tcx>>,
708709
) {
709710
if matches!(pat.ctor(), Constructor::NonExhaustive) {
710711
non_exhaustive_tys.insert(pat.ty());
711712
}
713+
if let Constructor::IntRange(range) = pat.ctor() {
714+
if range.is_beyond_boundaries(pat.ty(), tcx) {
715+
// The range denotes the values before `isize::MIN` or the values after `usize::MAX`/`isize::MAX`.
716+
non_exhaustive_tys.insert(pat.ty());
717+
}
718+
}
712719
pat.iter_fields()
713-
.for_each(|field_pat| collect_non_exhaustive_tys(field_pat, non_exhaustive_tys))
720+
.for_each(|field_pat| collect_non_exhaustive_tys(tcx, field_pat, non_exhaustive_tys))
714721
}
715722

716723
/// Report that a match is not exhaustive.
@@ -764,16 +771,24 @@ fn non_exhaustive_match<'p, 'tcx>(
764771
adt_defined_here(cx, &mut err, scrut_ty, &witnesses);
765772
err.note(format!("the matched value is of type `{}`", scrut_ty));
766773

767-
if !is_empty_match && witnesses.len() == 1 {
774+
if !is_empty_match {
768775
let mut non_exhaustive_tys = FxHashSet::default();
769-
collect_non_exhaustive_tys(&witnesses[0], &mut non_exhaustive_tys);
776+
// Look at the first witness.
777+
collect_non_exhaustive_tys(cx.tcx, &witnesses[0], &mut non_exhaustive_tys);
770778

771779
for ty in non_exhaustive_tys {
772780
if ty.is_ptr_sized_integral() {
773-
err.note(format!(
774-
"`{ty}` does not have a fixed maximum value, so a wildcard `_` is necessary to match \
775-
exhaustively",
781+
if ty == cx.tcx.types.usize {
782+
err.note(format!(
783+
"`{ty}` does not have a fixed maximum value, so half-open ranges are necessary to match \
784+
exhaustively",
776785
));
786+
} else if ty == cx.tcx.types.isize {
787+
err.note(format!(
788+
"`{ty}` does not have fixed minimum and maximum values, so half-open ranges are necessary to match \
789+
exhaustively",
790+
));
791+
}
777792
if cx.tcx.sess.is_nightly_build() {
778793
err.help(format!(
779794
"add `#![feature(precise_pointer_size_matching)]` to the crate attributes to \

‎compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs

+94-43
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ use rustc_hir::{HirId, RangeEnd};
5656
use rustc_index::Idx;
5757
use rustc_middle::middle::stability::EvalResult;
5858
use rustc_middle::mir;
59+
use rustc_middle::mir::interpret::Scalar;
5960
use rustc_middle::thir::{FieldPat, Pat, PatKind, PatRange, PatRangeBoundary};
6061
use rustc_middle::ty::layout::IntegerExt;
6162
use rustc_middle::ty::{self, Ty, TyCtxt, VariantDef};
@@ -141,20 +142,32 @@ impl MaybeInfiniteInt {
141142
PatRangeBoundary::PosInfinity => PosInfinity,
142143
}
143144
}
145+
// This could change from finite to infinite if we got `usize::MAX+1` after range splitting.
144146
fn to_pat_range_bdy<'tcx>(self, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> PatRangeBoundary<'tcx> {
145147
match self {
146148
NegInfinity => PatRangeBoundary::NegInfinity,
147149
Finite(x) => {
148150
let bias = Self::signed_bias(tcx, ty);
149151
let bits = x ^ bias;
150-
let env = ty::ParamEnv::empty().and(ty);
151-
let value = mir::Const::from_bits(tcx, bits, env);
152-
PatRangeBoundary::Finite(value)
152+
let size = ty.primitive_size(tcx);
153+
match Scalar::try_from_uint(bits, size) {
154+
Some(scalar) => {
155+
let value = mir::Const::from_scalar(tcx, scalar, ty);
156+
PatRangeBoundary::Finite(value)
157+
}
158+
// The value doesn't fit. Since `x >= 0` and 0 always encodes the minimum value
159+
// for a type, the problem isn't that the value is too small. So it must be too
160+
// large.
161+
None => PatRangeBoundary::PosInfinity,
162+
}
153163
}
154164
JustAfterMax | PosInfinity => PatRangeBoundary::PosInfinity,
155165
}
156166
}
157167

168+
fn is_finite(self) -> bool {
169+
matches!(self, Finite(_))
170+
}
158171
fn minus_one(self) -> Self {
159172
match self {
160173
Finite(n) => match n.checked_sub(1) {
@@ -171,22 +184,24 @@ impl MaybeInfiniteInt {
171184
Some(m) => Finite(m),
172185
None => JustAfterMax,
173186
},
187+
JustAfterMax => bug!(),
174188
x => x,
175189
}
176190
}
177191
}
178192

179-
/// An inclusive interval, used for precise integer exhaustiveness checking.
180-
/// `IntRange`s always store a contiguous range.
193+
/// An inclusive interval, used for precise integer exhaustiveness checking. `IntRange`s always
194+
/// store a contiguous range.
181195
///
182-
/// `IntRange` is never used to encode an empty range or a "range" that wraps
183-
/// around the (offset) space: i.e., `range.lo <= range.hi`.
196+
/// `IntRange` is never used to encode an empty range or a "range" that wraps around the (offset)
197+
/// space: i.e., `range.lo <= range.hi`.
184198
///
185-
/// The range can have open ends.
199+
/// Note: the range can be `NegInfinity..=NegInfinity` or `PosInfinity..=PosInfinity` to represent
200+
/// the values before `isize::MIN` and after `isize::MAX`/`usize::MAX`.
186201
#[derive(Clone, Copy, PartialEq, Eq)]
187202
pub(crate) struct IntRange {
188-
lo: MaybeInfiniteInt, // Must not be `PosInfinity`.
189-
hi: MaybeInfiniteInt, // Must not be `NegInfinity`.
203+
lo: MaybeInfiniteInt,
204+
hi: MaybeInfiniteInt,
190205
}
191206

192207
impl IntRange {
@@ -197,7 +212,7 @@ impl IntRange {
197212

198213
/// Best effort; will not know that e.g. `255u8..` is a singleton.
199214
fn is_singleton(&self) -> bool {
200-
self.lo == self.hi
215+
self.lo == self.hi && self.lo.is_finite()
201216
}
202217

203218
#[inline]
@@ -242,7 +257,8 @@ impl IntRange {
242257
// `true` in the following cases:
243258
// 1 ------- // 1 -------
244259
// 2 -------- // 2 -------
245-
(self.lo == other.hi || self.hi == other.lo)
260+
((self.lo == other.hi && self.lo.is_finite())
261+
|| (self.hi == other.lo && self.hi.is_finite()))
246262
&& !self.is_singleton()
247263
&& !other.is_singleton()
248264
}
@@ -327,18 +343,49 @@ impl IntRange {
327343
})
328344
}
329345

346+
/// Whether the range denotes the values before `isize::MIN` or the values after
347+
/// `usize::MAX`/`isize::MAX`.
348+
pub(crate) fn is_beyond_boundaries<'tcx>(&self, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> bool {
349+
// First check if we are usize/isize to avoid unnecessary `to_pat_range_bdy`.
350+
ty.is_ptr_sized_integral() && !tcx.features().precise_pointer_size_matching && {
351+
let lo = self.lo.to_pat_range_bdy(ty, tcx);
352+
let hi = self.hi.to_pat_range_bdy(ty, tcx);
353+
matches!(lo, PatRangeBoundary::PosInfinity)
354+
|| matches!(hi, PatRangeBoundary::NegInfinity)
355+
}
356+
}
330357
/// Only used for displaying the range.
331358
fn to_pat<'tcx>(&self, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Pat<'tcx> {
332-
let lo = self.lo.to_pat_range_bdy(ty, tcx);
333-
let hi = self.hi.to_pat_range_bdy(ty, tcx);
334-
335-
let kind = if self.is_singleton() {
359+
let kind = if matches!((self.lo, self.hi), (NegInfinity, PosInfinity)) {
360+
PatKind::Wild
361+
} else if self.is_singleton() {
362+
let lo = self.lo.to_pat_range_bdy(ty, tcx);
336363
let value = lo.as_finite().unwrap();
337364
PatKind::Constant { value }
338-
} else if matches!((self.lo, self.hi), (NegInfinity, PosInfinity)) {
339-
PatKind::Wild
340365
} else {
341-
PatKind::Range(Box::new(PatRange { lo, hi, end: RangeEnd::Included, ty }))
366+
let mut lo = self.lo.to_pat_range_bdy(ty, tcx);
367+
let mut hi = self.hi.to_pat_range_bdy(ty, tcx);
368+
let end = if hi.is_finite() {
369+
RangeEnd::Included
370+
} else {
371+
// `0..=` isn't a valid pattern.
372+
RangeEnd::Excluded
373+
};
374+
if matches!(hi, PatRangeBoundary::NegInfinity) {
375+
// The range denotes the values before `isize::MIN`.
376+
let c = ty.numeric_min_val(tcx).unwrap();
377+
let value = mir::Const::from_ty_const(c, tcx);
378+
hi = PatRangeBoundary::Finite(value);
379+
}
380+
if matches!(lo, PatRangeBoundary::PosInfinity) {
381+
// The range denotes the values after `usize::MAX`/`isize::MAX`.
382+
// We represent this as `usize::MAX..` which is slightly incorrect but probably
383+
// clear enough.
384+
let c = ty.numeric_max_val(tcx).unwrap();
385+
let value = mir::Const::from_ty_const(c, tcx);
386+
lo = PatRangeBoundary::Finite(value);
387+
}
388+
PatKind::Range(Box::new(PatRange { lo, hi, end, ty }))
342389
};
343390

344391
Pat { ty, span: DUMMY_SP, kind }
@@ -905,9 +952,7 @@ pub(super) enum ConstructorSet {
905952
Bool,
906953
/// The type is spanned by integer values. The range or ranges give the set of allowed values.
907954
/// The second range is only useful for `char`.
908-
/// `non_exhaustive` is used when the range is not allowed to be matched exhaustively (that's
909-
/// for usize/isize).
910-
Integers { range_1: IntRange, range_2: Option<IntRange>, non_exhaustive: bool },
955+
Integers { range_1: IntRange, range_2: Option<IntRange> },
911956
/// The type is matched by slices. The usize is the compile-time length of the array, if known.
912957
Slice(Option<usize>),
913958
/// The type is matched by slices whose elements are uninhabited.
@@ -965,27 +1010,37 @@ impl ConstructorSet {
9651010
Self::Integers {
9661011
range_1: make_range('\u{0000}' as u128, '\u{D7FF}' as u128),
9671012
range_2: Some(make_range('\u{E000}' as u128, '\u{10FFFF}' as u128)),
968-
non_exhaustive: false,
9691013
}
9701014
}
9711015
&ty::Int(ity) => {
972-
// `usize`/`isize` are not allowed to be matched exhaustively unless the
973-
// `precise_pointer_size_matching` feature is enabled.
974-
let non_exhaustive =
975-
ty.is_ptr_sized_integral() && !cx.tcx.features().precise_pointer_size_matching;
976-
let bits = Integer::from_int_ty(&cx.tcx, ity).size().bits() as u128;
977-
let min = 1u128 << (bits - 1);
978-
let max = min - 1;
979-
Self::Integers { range_1: make_range(min, max), non_exhaustive, range_2: None }
1016+
let range = if ty.is_ptr_sized_integral()
1017+
&& !cx.tcx.features().precise_pointer_size_matching
1018+
{
1019+
// The min/max values of `isize` are not allowed to be observed unless the
1020+
// `precise_pointer_size_matching` feature is enabled.
1021+
IntRange { lo: NegInfinity, hi: PosInfinity }
1022+
} else {
1023+
let bits = Integer::from_int_ty(&cx.tcx, ity).size().bits() as u128;
1024+
let min = 1u128 << (bits - 1);
1025+
let max = min - 1;
1026+
make_range(min, max)
1027+
};
1028+
Self::Integers { range_1: range, range_2: None }
9801029
}
9811030
&ty::Uint(uty) => {
982-
// `usize`/`isize` are not allowed to be matched exhaustively unless the
983-
// `precise_pointer_size_matching` feature is enabled.
984-
let non_exhaustive =
985-
ty.is_ptr_sized_integral() && !cx.tcx.features().precise_pointer_size_matching;
986-
let size = Integer::from_uint_ty(&cx.tcx, uty).size();
987-
let max = size.truncate(u128::MAX);
988-
Self::Integers { range_1: make_range(0, max), non_exhaustive, range_2: None }
1031+
let range = if ty.is_ptr_sized_integral()
1032+
&& !cx.tcx.features().precise_pointer_size_matching
1033+
{
1034+
// The max value of `usize` is not allowed to be observed unless the
1035+
// `precise_pointer_size_matching` feature is enabled.
1036+
let lo = MaybeInfiniteInt::new_finite(cx.tcx, ty, 0);
1037+
IntRange { lo, hi: PosInfinity }
1038+
} else {
1039+
let size = Integer::from_uint_ty(&cx.tcx, uty).size();
1040+
let max = size.truncate(u128::MAX);
1041+
make_range(0, max)
1042+
};
1043+
Self::Integers { range_1: range, range_2: None }
9891044
}
9901045
ty::Array(sub_ty, len) if len.try_eval_target_usize(cx.tcx, cx.param_env).is_some() => {
9911046
let len = len.eval_target_usize(cx.tcx, cx.param_env) as usize;
@@ -1140,7 +1195,7 @@ impl ConstructorSet {
11401195
missing.push(Bool(true));
11411196
}
11421197
}
1143-
ConstructorSet::Integers { range_1, range_2, non_exhaustive } => {
1198+
ConstructorSet::Integers { range_1, range_2 } => {
11441199
let seen_ranges: Vec<_> =
11451200
seen.map(|ctor| ctor.as_int_range().unwrap().clone()).collect();
11461201
for (seen, splitted_range) in range_1.split(seen_ranges.iter().cloned()) {
@@ -1157,10 +1212,6 @@ impl ConstructorSet {
11571212
}
11581213
}
11591214
}
1160-
1161-
if *non_exhaustive {
1162-
missing.push(NonExhaustive);
1163-
}
11641215
}
11651216
&ConstructorSet::Slice(array_len) => {
11661217
let seen_slices = seen.map(|c| c.as_slice().unwrap());
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
fn main() {
22
match 0usize {
3-
//~^ ERROR non-exhaustive patterns: `_` not covered
4-
//~| NOTE pattern `_` not covered
3+
//~^ ERROR non-exhaustive patterns: `usize::MAX..` not covered
4+
//~| NOTE pattern `usize::MAX..` not covered
55
//~| NOTE the matched value is of type `usize`
66
//~| NOTE `usize` does not have a fixed maximum value
77
0..=usize::MAX => {}
88
}
99

1010
match 0isize {
11-
//~^ ERROR non-exhaustive patterns: `_` not covered
12-
//~| NOTE pattern `_` not covered
11+
//~^ ERROR non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered
12+
//~| NOTE patterns `..isize::MIN` and `isize::MAX..` not covered
1313
//~| NOTE the matched value is of type `isize`
14-
//~| NOTE `isize` does not have a fixed maximum value
14+
//~| NOTE `isize` does not have fixed minimum and maximum values
1515
isize::MIN..=isize::MAX => {}
1616
}
1717
}

‎tests/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,31 @@
1-
error[E0004]: non-exhaustive patterns: `_` not covered
1+
error[E0004]: non-exhaustive patterns: `usize::MAX..` not covered
22
--> $DIR/feature-gate-precise_pointer_size_matching.rs:2:11
33
|
44
LL | match 0usize {
5-
| ^^^^^^ pattern `_` not covered
5+
| ^^^^^^ pattern `usize::MAX..` not covered
66
|
77
= note: the matched value is of type `usize`
8-
= note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
8+
= note: `usize` does not have a fixed maximum value, so half-open ranges are necessary to match exhaustively
99
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
1010
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
1111
|
1212
LL ~ 0..=usize::MAX => {},
13-
LL + _ => todo!()
13+
LL + usize::MAX.. => todo!()
1414
|
1515

16-
error[E0004]: non-exhaustive patterns: `_` not covered
16+
error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered
1717
--> $DIR/feature-gate-precise_pointer_size_matching.rs:10:11
1818
|
1919
LL | match 0isize {
20-
| ^^^^^^ pattern `_` not covered
20+
| ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered
2121
|
2222
= note: the matched value is of type `isize`
23-
= note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
23+
= note: `isize` does not have fixed minimum and maximum values, so half-open ranges are necessary to match exhaustively
2424
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
25-
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
25+
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
2626
|
2727
LL ~ isize::MIN..=isize::MAX => {},
28-
LL + _ => todo!()
28+
LL + ..isize::MIN | isize::MAX.. => todo!()
2929
|
3030

3131
error: aborting due to 2 previous errors

‎tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.allow.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0004]: non-exhaustive patterns: type `usize` is non-empty
2-
--> $DIR/pointer-sized-int.rs:58:11
2+
--> $DIR/pointer-sized-int.rs:54:11
33
|
44
LL | match 7usize {}
55
| ^^^^^^

‎tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr

+69-125
Large diffs are not rendered by default.

‎tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs

-4
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ fn main() {
2222
}
2323

2424
m!(0usize, 0..);
25-
//[deny]~^ ERROR non-exhaustive patterns
2625
m!(0usize, 0..=usize::MAX);
2726
//[deny]~^ ERROR non-exhaustive patterns
2827
m!(0usize, 0..5 | 5..=usize::MAX);
@@ -32,10 +31,8 @@ fn main() {
3231
m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false));
3332
//[deny]~^ ERROR non-exhaustive patterns
3433
m!(0usize, 0..=usize::MAX | usize::MAX..);
35-
//[deny]~^ ERROR non-exhaustive patterns
3634

3735
m!(0isize, ..0 | 0..);
38-
//[deny]~^ ERROR non-exhaustive patterns
3936
m!(0isize, isize::MIN..=isize::MAX);
4037
//[deny]~^ ERROR non-exhaustive patterns
4138
m!(0isize, isize::MIN..5 | 5..=isize::MAX);
@@ -46,7 +43,6 @@ fn main() {
4643
| (5..=isize::MAX, true) | (isize::MIN..=isize::MAX, false));
4744
//[deny]~^^ ERROR non-exhaustive patterns
4845
m!(0isize, ..=isize::MIN | isize::MIN..=isize::MAX | isize::MAX..);
49-
//[deny]~^ ERROR non-exhaustive patterns
5046

5147
match 0isize {
5248
//[deny]~^ ERROR non-exhaustive patterns
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
// This tests that the lint message explains the reason for the error.
22
fn main() {
33
match 0usize {
4-
//~^ ERROR non-exhaustive patterns: `_` not covered
5-
//~| NOTE pattern `_` not covered
4+
//~^ ERROR non-exhaustive patterns: `usize::MAX..` not covered
5+
//~| NOTE pattern `usize::MAX..` not covered
66
//~| NOTE the matched value is of type `usize`
77
//~| NOTE `usize` does not have a fixed maximum value
88
0..=usize::MAX => {}
99
}
1010

1111
match 0isize {
12-
//~^ ERROR non-exhaustive patterns: `_` not covered
13-
//~| NOTE pattern `_` not covered
12+
//~^ ERROR non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered
13+
//~| NOTE patterns `..isize::MIN` and `isize::MAX..` not covered
1414
//~| NOTE the matched value is of type `isize`
15-
//~| NOTE `isize` does not have a fixed maximum value
15+
//~| NOTE `isize` does not have fixed minimum and maximum values
1616
isize::MIN..=isize::MAX => {}
1717
}
1818
}

‎tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,31 @@
1-
error[E0004]: non-exhaustive patterns: `_` not covered
1+
error[E0004]: non-exhaustive patterns: `usize::MAX..` not covered
22
--> $DIR/precise_pointer_matching-message.rs:3:11
33
|
44
LL | match 0usize {
5-
| ^^^^^^ pattern `_` not covered
5+
| ^^^^^^ pattern `usize::MAX..` not covered
66
|
77
= note: the matched value is of type `usize`
8-
= note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
8+
= note: `usize` does not have a fixed maximum value, so half-open ranges are necessary to match exhaustively
99
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
1010
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
1111
|
1212
LL ~ 0..=usize::MAX => {},
13-
LL + _ => todo!()
13+
LL + usize::MAX.. => todo!()
1414
|
1515

16-
error[E0004]: non-exhaustive patterns: `_` not covered
16+
error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered
1717
--> $DIR/precise_pointer_matching-message.rs:11:11
1818
|
1919
LL | match 0isize {
20-
| ^^^^^^ pattern `_` not covered
20+
| ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered
2121
|
2222
= note: the matched value is of type `isize`
23-
= note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
23+
= note: `isize` does not have fixed minimum and maximum values, so half-open ranges are necessary to match exhaustively
2424
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
25-
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
25+
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
2626
|
2727
LL ~ isize::MIN..=isize::MAX => {},
28-
LL + _ => todo!()
28+
LL + ..isize::MIN | isize::MAX.. => todo!()
2929
|
3030

3131
error: aborting due to 2 previous errors

‎tests/ui/pattern/usefulness/issue-85222-types-containing-non-exhaustive-types.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@ struct B<T, U>(T, U);
66

77
fn main() {
88
match 0 {
9-
//~^ ERROR non-exhaustive patterns: `_` not covered [E0004]
9+
//~^ ERROR non-exhaustive patterns: `usize::MAX..` not covered [E0004]
1010
0 => (),
1111
1..=usize::MAX => (),
1212
}
1313

1414
match (0usize, 0usize) {
15-
//~^ ERROR non-exhaustive patterns: `(_, _)` not covered [E0004]
15+
//~^ ERROR non-exhaustive patterns: `(usize::MAX.., _)` not covered [E0004]
1616
(0, 0) => (),
1717
(1..=usize::MAX, 1..=usize::MAX) => (),
1818
}
1919

2020
match (0isize, 0usize) {
21-
//~^ ERROR non-exhaustive patterns: `(_, _)` not covered [E0004]
21+
//~^ ERROR non-exhaustive patterns: `(..isize::MIN, _)` and `(isize::MAX.., _)` not covered [E0004]
2222
(isize::MIN..=isize::MAX, 0) => (),
2323
(isize::MIN..=isize::MAX, 1..=usize::MAX) => (),
2424
}
@@ -30,14 +30,14 @@ fn main() {
3030
}
3131

3232
match Some(4) {
33-
//~^ ERROR non-exhaustive patterns: `Some(_)` not covered
33+
//~^ ERROR non-exhaustive patterns: `Some(usize::MAX..)` not covered
3434
Some(0) => (),
3535
Some(1..=usize::MAX) => (),
3636
None => (),
3737
}
3838

3939
match Some(Some(Some(0))) {
40-
//~^ ERROR non-exhaustive patterns: `Some(Some(Some(_)))` not covered
40+
//~^ ERROR non-exhaustive patterns: `Some(Some(Some(usize::MAX..)))` not covered
4141
Some(Some(Some(0))) => (),
4242
Some(Some(Some(1..=usize::MAX))) => (),
4343
Some(Some(None)) => (),
@@ -46,21 +46,21 @@ fn main() {
4646
}
4747

4848
match (A { a: 0usize }) {
49-
//~^ ERROR non-exhaustive patterns: `A { .. }` not covered [E0004]
49+
//~^ ERROR non-exhaustive patterns: `A { a: usize::MAX.. }` not covered [E0004]
5050
A { a: 0 } => (),
5151
A { a: 1..=usize::MAX } => (),
5252
}
5353

5454
match B(0isize, 0usize) {
55-
//~^ ERROR non-exhaustive patterns: `B(_, _)` not covered [E0004]
55+
//~^ ERROR non-exhaustive patterns: `B(..isize::MIN, _)` and `B(isize::MAX.., _)` not covered [E0004]
5656
B(isize::MIN..=isize::MAX, 0) => (),
5757
B(isize::MIN..=isize::MAX, 1..=usize::MAX) => (),
5858
}
5959

6060
// Should report only the note about usize not having fixed max value and not report
6161
// report the note about isize
6262
match B(0isize, 0usize) {
63-
//~^ ERROR non-exhaustive patterns: `B(_, _)` not covered [E0004]
63+
//~^ ERROR non-exhaustive patterns: `B(_, usize::MAX..)` not covered [E0004]
6464
B(_, 0) => (),
6565
B(_, 1..=usize::MAX) => (),
6666
}

‎tests/ui/pattern/usefulness/issue-85222-types-containing-non-exhaustive-types.stderr

+34-34
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,46 @@
1-
error[E0004]: non-exhaustive patterns: `_` not covered
1+
error[E0004]: non-exhaustive patterns: `usize::MAX..` not covered
22
--> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:8:11
33
|
44
LL | match 0 {
5-
| ^ pattern `_` not covered
5+
| ^ pattern `usize::MAX..` not covered
66
|
77
= note: the matched value is of type `usize`
8-
= note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
8+
= note: `usize` does not have a fixed maximum value, so half-open ranges are necessary to match exhaustively
99
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
1010
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
1111
|
1212
LL ~ 1..=usize::MAX => (),
13-
LL ~ _ => todo!(),
13+
LL ~ usize::MAX.. => todo!(),
1414
|
1515

16-
error[E0004]: non-exhaustive patterns: `(_, _)` not covered
16+
error[E0004]: non-exhaustive patterns: `(usize::MAX.., _)` not covered
1717
--> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:14:11
1818
|
1919
LL | match (0usize, 0usize) {
20-
| ^^^^^^^^^^^^^^^^ pattern `(_, _)` not covered
20+
| ^^^^^^^^^^^^^^^^ pattern `(usize::MAX.., _)` not covered
2121
|
2222
= note: the matched value is of type `(usize, usize)`
23-
= note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
23+
= note: `usize` does not have a fixed maximum value, so half-open ranges are necessary to match exhaustively
2424
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
2525
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
2626
|
2727
LL ~ (1..=usize::MAX, 1..=usize::MAX) => (),
28-
LL ~ (_, _) => todo!(),
28+
LL ~ (usize::MAX.., _) => todo!(),
2929
|
3030

31-
error[E0004]: non-exhaustive patterns: `(_, _)` not covered
31+
error[E0004]: non-exhaustive patterns: `(..isize::MIN, _)` and `(isize::MAX.., _)` not covered
3232
--> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:20:11
3333
|
3434
LL | match (0isize, 0usize) {
35-
| ^^^^^^^^^^^^^^^^ pattern `(_, _)` not covered
35+
| ^^^^^^^^^^^^^^^^ patterns `(..isize::MIN, _)` and `(isize::MAX.., _)` not covered
3636
|
3737
= note: the matched value is of type `(isize, usize)`
38-
= note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
38+
= note: `isize` does not have fixed minimum and maximum values, so half-open ranges are necessary to match exhaustively
3939
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
40-
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
40+
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
4141
|
4242
LL ~ (isize::MIN..=isize::MAX, 1..=usize::MAX) => (),
43-
LL ~ (_, _) => todo!(),
43+
LL ~ (..isize::MIN, _) | (isize::MAX.., _) => todo!(),
4444
|
4545

4646
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
@@ -61,31 +61,31 @@ LL ~ None => {},
6161
LL + Some(_) => todo!()
6262
|
6363

64-
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
64+
error[E0004]: non-exhaustive patterns: `Some(usize::MAX..)` not covered
6565
--> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:32:11
6666
|
6767
LL | match Some(4) {
68-
| ^^^^^^^ pattern `Some(_)` not covered
68+
| ^^^^^^^ pattern `Some(usize::MAX..)` not covered
6969
|
7070
note: `Option<usize>` defined here
7171
--> $SRC_DIR/core/src/option.rs:LL:COL
7272
::: $SRC_DIR/core/src/option.rs:LL:COL
7373
|
7474
= note: not covered
7575
= note: the matched value is of type `Option<usize>`
76-
= note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
76+
= note: `usize` does not have a fixed maximum value, so half-open ranges are necessary to match exhaustively
7777
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
7878
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
7979
|
8080
LL ~ None => (),
81-
LL ~ Some(_) => todo!(),
81+
LL ~ Some(usize::MAX..) => todo!(),
8282
|
8383

84-
error[E0004]: non-exhaustive patterns: `Some(Some(Some(_)))` not covered
84+
error[E0004]: non-exhaustive patterns: `Some(Some(Some(usize::MAX..)))` not covered
8585
--> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:39:11
8686
|
8787
LL | match Some(Some(Some(0))) {
88-
| ^^^^^^^^^^^^^^^^^^^ pattern `Some(Some(Some(_)))` not covered
88+
| ^^^^^^^^^^^^^^^^^^^ pattern `Some(Some(Some(usize::MAX..)))` not covered
8989
|
9090
note: `Option<Option<Option<usize>>>` defined here
9191
--> $SRC_DIR/core/src/option.rs:LL:COL
@@ -97,72 +97,72 @@ note: `Option<Option<Option<usize>>>` defined here
9797
|
9898
= note: not covered
9999
= note: the matched value is of type `Option<Option<Option<usize>>>`
100-
= note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
100+
= note: `usize` does not have a fixed maximum value, so half-open ranges are necessary to match exhaustively
101101
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
102102
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
103103
|
104104
LL ~ None => (),
105-
LL ~ Some(Some(Some(_))) => todo!(),
105+
LL ~ Some(Some(Some(usize::MAX..))) => todo!(),
106106
|
107107

108-
error[E0004]: non-exhaustive patterns: `A { .. }` not covered
108+
error[E0004]: non-exhaustive patterns: `A { a: usize::MAX.. }` not covered
109109
--> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:48:11
110110
|
111111
LL | match (A { a: 0usize }) {
112-
| ^^^^^^^^^^^^^^^^^ pattern `A { .. }` not covered
112+
| ^^^^^^^^^^^^^^^^^ pattern `A { a: usize::MAX.. }` not covered
113113
|
114114
note: `A<usize>` defined here
115115
--> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:1:8
116116
|
117117
LL | struct A<T> {
118118
| ^
119119
= note: the matched value is of type `A<usize>`
120-
= note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
120+
= note: `usize` does not have a fixed maximum value, so half-open ranges are necessary to match exhaustively
121121
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
122122
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
123123
|
124124
LL ~ A { a: 1..=usize::MAX } => (),
125-
LL ~ A { .. } => todo!(),
125+
LL ~ A { a: usize::MAX.. } => todo!(),
126126
|
127127

128-
error[E0004]: non-exhaustive patterns: `B(_, _)` not covered
128+
error[E0004]: non-exhaustive patterns: `B(..isize::MIN, _)` and `B(isize::MAX.., _)` not covered
129129
--> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:54:11
130130
|
131131
LL | match B(0isize, 0usize) {
132-
| ^^^^^^^^^^^^^^^^^ pattern `B(_, _)` not covered
132+
| ^^^^^^^^^^^^^^^^^ patterns `B(..isize::MIN, _)` and `B(isize::MAX.., _)` not covered
133133
|
134134
note: `B<isize, usize>` defined here
135135
--> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:5:8
136136
|
137137
LL | struct B<T, U>(T, U);
138138
| ^
139139
= note: the matched value is of type `B<isize, usize>`
140-
= note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
140+
= note: `isize` does not have fixed minimum and maximum values, so half-open ranges are necessary to match exhaustively
141141
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
142-
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
142+
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
143143
|
144144
LL ~ B(isize::MIN..=isize::MAX, 1..=usize::MAX) => (),
145-
LL ~ B(_, _) => todo!(),
145+
LL ~ B(..isize::MIN, _) | B(isize::MAX.., _) => todo!(),
146146
|
147147

148-
error[E0004]: non-exhaustive patterns: `B(_, _)` not covered
148+
error[E0004]: non-exhaustive patterns: `B(_, usize::MAX..)` not covered
149149
--> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:62:11
150150
|
151151
LL | match B(0isize, 0usize) {
152-
| ^^^^^^^^^^^^^^^^^ pattern `B(_, _)` not covered
152+
| ^^^^^^^^^^^^^^^^^ pattern `B(_, usize::MAX..)` not covered
153153
|
154154
note: `B<isize, usize>` defined here
155155
--> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:5:8
156156
|
157157
LL | struct B<T, U>(T, U);
158158
| ^
159159
= note: the matched value is of type `B<isize, usize>`
160-
= note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
160+
= note: `usize` does not have a fixed maximum value, so half-open ranges are necessary to match exhaustively
161161
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
162162
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
163163
|
164164
LL ~ B(_, 1..=usize::MAX) => (),
165-
LL ~ B(_, _) => todo!(),
165+
LL ~ B(_, usize::MAX..) => todo!(),
166166
|
167167

168168
error: aborting due to 9 previous errors

‎tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs

+33-20
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,101 @@
11
struct Foo {
22
first: bool,
3-
second: Option<[usize; 4]>
3+
second: Option<[usize; 4]>,
44
}
55

66
fn struct_with_a_nested_enum_and_vector() {
77
match (Foo { first: true, second: None }) {
8-
//~^ ERROR non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered
8+
//~^ ERROR non-exhaustive patterns: `Foo { first: false, second: Some([0_usize, _, _, _]) }` and `Foo { first: false, second: Some([2_usize.., _, _, _]) }` not covered
99
Foo { first: true, second: None } => (),
1010
Foo { first: true, second: Some(_) } => (),
1111
Foo { first: false, second: None } => (),
12-
Foo { first: false, second: Some([1, 2, 3, 4]) } => ()
12+
Foo { first: false, second: Some([1, 2, 3, 4]) } => (),
1313
}
1414
}
1515

1616
enum Color {
1717
Red,
1818
Green,
19-
CustomRGBA { a: bool, r: u8, g: u8, b: u8 }
19+
CustomRGBA { a: bool, r: u8, g: u8, b: u8 },
2020
}
2121

2222
fn enum_with_single_missing_variant() {
2323
match Color::Red {
24-
//~^ ERROR non-exhaustive patterns: `Color::Red` not covered
24+
//~^ ERROR non-exhaustive patterns: `Color::Red` not covered
2525
Color::CustomRGBA { .. } => (),
26-
Color::Green => ()
26+
Color::Green => (),
2727
}
2828
}
2929

3030
enum Direction {
31-
North, East, South, West
31+
North,
32+
East,
33+
South,
34+
West,
3235
}
3336

3437
fn enum_with_multiple_missing_variants() {
3538
match Direction::North {
36-
//~^ ERROR non-exhaustive patterns: `Direction::East`, `Direction::South` and `Direction::West` not covered
37-
Direction::North => ()
39+
//~^ ERROR non-exhaustive patterns: `Direction::East`, `Direction::South` and `Direction::West` not covered
40+
Direction::North => (),
3841
}
3942
}
4043

4144
enum ExcessiveEnum {
42-
First, Second, Third, Fourth, Fifth, Sixth, Seventh, Eighth, Ninth, Tenth, Eleventh, Twelfth
45+
First,
46+
Second,
47+
Third,
48+
Fourth,
49+
Fifth,
50+
Sixth,
51+
Seventh,
52+
Eighth,
53+
Ninth,
54+
Tenth,
55+
Eleventh,
56+
Twelfth,
4357
}
4458

4559
fn enum_with_excessive_missing_variants() {
4660
match ExcessiveEnum::First {
47-
//~^ ERROR `ExcessiveEnum::Second`, `ExcessiveEnum::Third`, `ExcessiveEnum::Fourth` and 8 more not covered
48-
49-
ExcessiveEnum::First => ()
61+
//~^ ERROR `ExcessiveEnum::Second`, `ExcessiveEnum::Third`, `ExcessiveEnum::Fourth` and 8 more not covered
62+
ExcessiveEnum::First => (),
5063
}
5164
}
5265

5366
fn enum_struct_variant() {
5467
match Color::Red {
55-
//~^ ERROR non-exhaustive patterns: `Color::CustomRGBA { a: true, .. }` not covered
68+
//~^ ERROR non-exhaustive patterns: `Color::CustomRGBA { a: true, .. }` not covered
5669
Color::Red => (),
5770
Color::Green => (),
5871
Color::CustomRGBA { a: false, r: _, g: _, b: 0 } => (),
59-
Color::CustomRGBA { a: false, r: _, g: _, b: _ } => ()
72+
Color::CustomRGBA { a: false, r: _, g: _, b: _ } => (),
6073
}
6174
}
6275

6376
enum Enum {
6477
First,
65-
Second(bool)
78+
Second(bool),
6679
}
6780

6881
fn vectors_with_nested_enums() {
6982
let x: &'static [Enum] = &[Enum::First, Enum::Second(false)];
7083
match *x {
71-
//~^ ERROR non-exhaustive patterns: `[Enum::Second(true), Enum::Second(false)]` not covered
84+
//~^ ERROR non-exhaustive patterns: `[Enum::Second(true), Enum::Second(false)]` not covered
7285
[] => (),
7386
[_] => (),
7487
[Enum::First, _] => (),
7588
[Enum::Second(true), Enum::First] => (),
7689
[Enum::Second(true), Enum::Second(true)] => (),
7790
[Enum::Second(false), _] => (),
78-
[_, _, ref tail @ .., _] => ()
91+
[_, _, ref tail @ .., _] => (),
7992
}
8093
}
8194

8295
fn missing_nil() {
8396
match ((), false) {
84-
//~^ ERROR non-exhaustive patterns: `((), false)` not covered
85-
((), true) => ()
97+
//~^ ERROR non-exhaustive patterns: `((), false)` not covered
98+
((), true) => (),
8699
}
87100
}
88101

‎tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr

+25-25
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
1-
error[E0004]: non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered
1+
error[E0004]: non-exhaustive patterns: `Foo { first: false, second: Some([0_usize, _, _, _]) }` and `Foo { first: false, second: Some([2_usize.., _, _, _]) }` not covered
22
--> $DIR/non-exhaustive-pattern-witness.rs:7:11
33
|
44
LL | match (Foo { first: true, second: None }) {
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { first: false, second: Some([_, _, _, _]) }` not covered
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo { first: false, second: Some([0_usize, _, _, _]) }` and `Foo { first: false, second: Some([2_usize.., _, _, _]) }` not covered
66
|
77
note: `Foo` defined here
88
--> $DIR/non-exhaustive-pattern-witness.rs:1:8
99
|
1010
LL | struct Foo {
1111
| ^^^
1212
= note: the matched value is of type `Foo`
13-
= note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
14-
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
15-
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
13+
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
1614
|
1715
LL ~ Foo { first: false, second: Some([1, 2, 3, 4]) } => (),
18-
LL + Foo { first: false, second: Some([_, _, _, _]) } => todo!()
16+
LL ~ Foo { first: false, second: Some([0_usize, _, _, _]) } | Foo { first: false, second: Some([2_usize.., _, _, _]) } => todo!(),
1917
|
2018

2119
error[E0004]: non-exhaustive patterns: `Color::Red` not covered
@@ -35,52 +33,54 @@ LL | Red,
3533
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
3634
|
3735
LL ~ Color::Green => (),
38-
LL + Color::Red => todo!()
36+
LL ~ Color::Red => todo!(),
3937
|
4038

4139
error[E0004]: non-exhaustive patterns: `Direction::East`, `Direction::South` and `Direction::West` not covered
42-
--> $DIR/non-exhaustive-pattern-witness.rs:35:11
40+
--> $DIR/non-exhaustive-pattern-witness.rs:38:11
4341
|
4442
LL | match Direction::North {
4543
| ^^^^^^^^^^^^^^^^ patterns `Direction::East`, `Direction::South` and `Direction::West` not covered
4644
|
4745
note: `Direction` defined here
48-
--> $DIR/non-exhaustive-pattern-witness.rs:31:12
46+
--> $DIR/non-exhaustive-pattern-witness.rs:32:5
4947
|
5048
LL | enum Direction {
5149
| ---------
52-
LL | North, East, South, West
53-
| ^^^^ ^^^^^ ^^^^ not covered
54-
| | |
55-
| | not covered
56-
| not covered
50+
LL | North,
51+
LL | East,
52+
| ^^^^ not covered
53+
LL | South,
54+
| ^^^^^ not covered
55+
LL | West,
56+
| ^^^^ not covered
5757
= note: the matched value is of type `Direction`
5858
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
5959
|
6060
LL ~ Direction::North => (),
61-
LL + Direction::East | Direction::South | Direction::West => todo!()
61+
LL ~ Direction::East | Direction::South | Direction::West => todo!(),
6262
|
6363

6464
error[E0004]: non-exhaustive patterns: `ExcessiveEnum::Second`, `ExcessiveEnum::Third`, `ExcessiveEnum::Fourth` and 8 more not covered
65-
--> $DIR/non-exhaustive-pattern-witness.rs:46:11
65+
--> $DIR/non-exhaustive-pattern-witness.rs:60:11
6666
|
6767
LL | match ExcessiveEnum::First {
6868
| ^^^^^^^^^^^^^^^^^^^^ patterns `ExcessiveEnum::Second`, `ExcessiveEnum::Third`, `ExcessiveEnum::Fourth` and 8 more not covered
6969
|
7070
note: `ExcessiveEnum` defined here
71-
--> $DIR/non-exhaustive-pattern-witness.rs:41:6
71+
--> $DIR/non-exhaustive-pattern-witness.rs:44:6
7272
|
7373
LL | enum ExcessiveEnum {
7474
| ^^^^^^^^^^^^^
7575
= note: the matched value is of type `ExcessiveEnum`
7676
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
7777
|
7878
LL ~ ExcessiveEnum::First => (),
79-
LL + _ => todo!()
79+
LL ~ _ => todo!(),
8080
|
8181

8282
error[E0004]: non-exhaustive patterns: `Color::CustomRGBA { a: true, .. }` not covered
83-
--> $DIR/non-exhaustive-pattern-witness.rs:54:11
83+
--> $DIR/non-exhaustive-pattern-witness.rs:67:11
8484
|
8585
LL | match Color::Red {
8686
| ^^^^^^^^^^ pattern `Color::CustomRGBA { a: true, .. }` not covered
@@ -91,17 +91,17 @@ note: `Color` defined here
9191
LL | enum Color {
9292
| -----
9393
...
94-
LL | CustomRGBA { a: bool, r: u8, g: u8, b: u8 }
94+
LL | CustomRGBA { a: bool, r: u8, g: u8, b: u8 },
9595
| ^^^^^^^^^^ not covered
9696
= note: the matched value is of type `Color`
9797
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
9898
|
9999
LL ~ Color::CustomRGBA { a: false, r: _, g: _, b: _ } => (),
100-
LL + Color::CustomRGBA { a: true, .. } => todo!()
100+
LL ~ Color::CustomRGBA { a: true, .. } => todo!(),
101101
|
102102

103103
error[E0004]: non-exhaustive patterns: `[Enum::Second(true), Enum::Second(false)]` not covered
104-
--> $DIR/non-exhaustive-pattern-witness.rs:70:11
104+
--> $DIR/non-exhaustive-pattern-witness.rs:83:11
105105
|
106106
LL | match *x {
107107
| ^^ pattern `[Enum::Second(true), Enum::Second(false)]` not covered
@@ -110,11 +110,11 @@ LL | match *x {
110110
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
111111
|
112112
LL ~ [_, _, ref tail @ .., _] => (),
113-
LL + [Enum::Second(true), Enum::Second(false)] => todo!()
113+
LL ~ [Enum::Second(true), Enum::Second(false)] => todo!(),
114114
|
115115

116116
error[E0004]: non-exhaustive patterns: `((), false)` not covered
117-
--> $DIR/non-exhaustive-pattern-witness.rs:83:11
117+
--> $DIR/non-exhaustive-pattern-witness.rs:96:11
118118
|
119119
LL | match ((), false) {
120120
| ^^^^^^^^^^^ pattern `((), false)` not covered
@@ -123,7 +123,7 @@ LL | match ((), false) {
123123
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
124124
|
125125
LL ~ ((), true) => (),
126-
LL + ((), false) => todo!()
126+
LL ~ ((), false) => todo!(),
127127
|
128128

129129
error: aborting due to 7 previous errors

‎tests/ui/pattern/usefulness/refutable-pattern-errors.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
1+
fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) {}
22
//~^ ERROR refutable pattern in function argument
3-
//~| `(_, _)` not covered
3+
//~| `(..=0_isize, _)` and `(2_isize.., _)` not covered
44

55
fn main() {
66
let (1, (Some(1), 2..=3)) = (1, (None, 2));

‎tests/ui/pattern/usefulness/refutable-pattern-errors.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0005]: refutable pattern in function argument
22
--> $DIR/refutable-pattern-errors.rs:1:9
33
|
4-
LL | fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
5-
| ^^^^^^^^^^^^^^^^^^^^^ pattern `(_, _)` not covered
4+
LL | fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) {}
5+
| ^^^^^^^^^^^^^^^^^^^^^ patterns `(..=0_isize, _)` and `(2_isize.., _)` not covered
66
|
77
= note: the matched value is of type `(isize, (Option<isize>, isize))`
88

Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
fn main() {
22
let f = |3: isize| println!("hello");
33
//~^ ERROR refutable pattern in function argument
4-
//~| `_` not covered
4+
//~| `..=2_isize` and `4_isize..` not covered
55
f(4);
66
}

‎tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0005]: refutable pattern in function argument
22
--> $DIR/refutable-pattern-in-fn-arg.rs:2:14
33
|
44
LL | let f = |3: isize| println!("hello");
5-
| ^ pattern `_` not covered
5+
| ^ patterns `..=2_isize` and `4_isize..` not covered
66
|
77
= note: the matched value is of type `isize`
88
help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits

‎tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
1-
error[E0004]: non-exhaustive patterns: `Foo(_, _)` not covered
1+
error[E0004]: non-exhaustive patterns: `Foo(..=0_isize, _)` and `Foo(3_isize.., _)` not covered
22
--> $DIR/tuple-struct-nonexhaustive.rs:5:11
33
|
44
LL | match x {
5-
| ^ pattern `Foo(_, _)` not covered
5+
| ^ patterns `Foo(..=0_isize, _)` and `Foo(3_isize.., _)` not covered
66
|
77
note: `Foo` defined here
88
--> $DIR/tuple-struct-nonexhaustive.rs:1:8
99
|
1010
LL | struct Foo(isize, isize);
1111
| ^^^
1212
= note: the matched value is of type `Foo`
13-
= note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
14-
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
15-
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
13+
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
1614
|
1715
LL ~ Foo(2, b) => println!("{}", b),
18-
LL + Foo(_, _) => todo!()
16+
LL + Foo(..=0_isize, _) | Foo(3_isize.., _) => todo!()
1917
|
2018

2119
error: aborting due to previous error

0 commit comments

Comments
 (0)
Please sign in to comment.