Skip to content

Commit f7179b8

Browse files
committed
Point at const when intended binding fall-through pattern is a const
``` error[E0004]: non-exhaustive patterns: `i32::MIN..=3_i32` and `5_i32..=i32::MAX` not covered --> $DIR/intended-binding-pattern-is-const.rs:2:11 | LL | match 1 { | ^ patterns `i32::MIN..=3_i32` and `5_i32..=i32::MAX` not covered LL | x => {} | - this pattern doesn't introduce a new catch-all binding, but rather pattern matches against the value of constant `x` | = note: the matched value is of type `i32` note: constant `x` defined here --> $DIR/intended-binding-pattern-is-const.rs:7:5 | LL | const x: i32 = 4; | ^^^^^^^^^^^^ help: if you meant to introduce a binding, use a different name | LL | x_var => {} | ++++ 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 | x => {}, i32::MIN..=3_i32 | 5_i32..=i32::MAX => todo!() | ++++++++++++++++++++++++++++++++++++++++++++++++ ```
1 parent 3a25296 commit f7179b8

File tree

3 files changed

+62
-4
lines changed

3 files changed

+62
-4
lines changed

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

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,13 +1116,13 @@ fn report_non_exhaustive_match<'p, 'tcx>(
11161116
if ty.is_ptr_sized_integral() {
11171117
if ty.inner() == cx.tcx.types.usize {
11181118
err.note(format!(
1119-
"`{ty}` does not have a fixed maximum value, so half-open ranges are necessary to match \
1120-
exhaustively",
1119+
"`{ty}` does not have a fixed maximum value, so half-open ranges are \
1120+
necessary to match exhaustively",
11211121
));
11221122
} else if ty.inner() == cx.tcx.types.isize {
11231123
err.note(format!(
1124-
"`{ty}` does not have fixed minimum and maximum values, so half-open ranges are necessary to match \
1125-
exhaustively",
1124+
"`{ty}` does not have fixed minimum and maximum values, so half-open \
1125+
ranges are necessary to match exhaustively",
11261126
));
11271127
}
11281128
} else if ty.inner() == cx.tcx.types.str_ {
@@ -1143,6 +1143,27 @@ fn report_non_exhaustive_match<'p, 'tcx>(
11431143
}
11441144
}
11451145

1146+
for &arm in arms {
1147+
let arm = &thir.arms[arm];
1148+
if let PatKind::Constant { opt_def: Some(def_id), .. } = arm.pattern.kind {
1149+
let const_name = cx.tcx.item_name(def_id);
1150+
err.span_label(
1151+
arm.pattern.span,
1152+
format!(
1153+
"this pattern doesn't introduce a new catch-all binding, but rather pattern \
1154+
matches against the value of constant `{const_name}`",
1155+
),
1156+
);
1157+
err.span_note(cx.tcx.def_span(def_id), format!("constant `{const_name}` defined here"));
1158+
err.span_suggestion_verbose(
1159+
arm.pattern.span.shrink_to_hi(),
1160+
"if you meant to introduce a binding, use a different name",
1161+
"_var".to_string(),
1162+
Applicability::MaybeIncorrect,
1163+
);
1164+
}
1165+
}
1166+
11461167
// Whether we suggest the actual missing patterns or `_`.
11471168
let suggest_the_witnesses = witnesses.len() < 4;
11481169
let suggested_arm = if suggest_the_witnesses {
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
fn main() {
2+
match 1 { //~ ERROR non-exhaustive patterns
3+
//~^ patterns `i32::MIN..=3_i32` and `5_i32..=i32::MAX` not covered
4+
//~| the matched value is of type `i32`
5+
x => {} //~ this pattern doesn't introduce a new catch-all binding
6+
//~^ HELP ensure that all possible cases are being handled
7+
//~| HELP if you meant to introduce a binding, use a different name
8+
}
9+
const x: i32 = 4; //~ NOTE constant `x` defined here
10+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error[E0004]: non-exhaustive patterns: `i32::MIN..=3_i32` and `5_i32..=i32::MAX` not covered
2+
--> $DIR/intended-binding-pattern-is-const.rs:2:11
3+
|
4+
LL | match 1 {
5+
| ^ patterns `i32::MIN..=3_i32` and `5_i32..=i32::MAX` not covered
6+
...
7+
LL | x => {}
8+
| - this pattern doesn't introduce a new catch-all binding, but rather pattern matches against the value of constant `x`
9+
|
10+
= note: the matched value is of type `i32`
11+
note: constant `x` defined here
12+
--> $DIR/intended-binding-pattern-is-const.rs:9:5
13+
|
14+
LL | const x: i32 = 4;
15+
| ^^^^^^^^^^^^
16+
help: if you meant to introduce a binding, use a different name
17+
|
18+
LL | x_var => {}
19+
| ++++
20+
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
21+
|
22+
LL | x => {}, i32::MIN..=3_i32 | 5_i32..=i32::MAX => todo!()
23+
| ++++++++++++++++++++++++++++++++++++++++++++++++
24+
25+
error: aborting due to 1 previous error
26+
27+
For more information about this error, try `rustc --explain E0004`.

0 commit comments

Comments
 (0)