Skip to content

Commit 084ca79

Browse files
committed
When finding a match expr with multiple arms that requires more, suggest it
Given ```rust match Some(42) { Some(0) => {} Some(1) => {} } ``` suggest ```rust match Some(42) { Some(0) => {} Some(1) => {} None | Some(_) => todo!(), } ```
1 parent 2383858 commit 084ca79

28 files changed

+263
-50
lines changed

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,21 @@ fn non_exhaustive_match<'p, 'tcx>(
604604
format!("{}{}{} => todo!()", comma, pre_indentation, pattern),
605605
));
606606
}
607+
[.., prev, last] if prev.span.ctxt() == last.span.ctxt() => {
608+
if let Ok(snippet) = sm.span_to_snippet(prev.span.between(last.span)) {
609+
let comma =
610+
if matches!(last.body.kind, hir::ExprKind::Block(..)) { "" } else { "," };
611+
suggestion = Some((
612+
last.span.shrink_to_hi(),
613+
format!(
614+
"{}{}{} => todo!()",
615+
comma,
616+
snippet.strip_prefix(",").unwrap_or(&snippet),
617+
pattern
618+
),
619+
));
620+
}
621+
}
607622
_ => {}
608623
}
609624

src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ LL | let _e = || { match e2 { E2::A => (), E2::B => () } };
3737
| ^^ pattern `_` not covered
3838
|
3939
= note: the matched value is of type `E2`, which is marked as non-exhaustive
40-
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
40+
help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
41+
|
42+
LL | let _e = || { match e2 { E2::A => (), E2::B => (), _ => todo!() } };
43+
| ++++++++++++++
4144

4245
error[E0505]: cannot move out of `e3` because it is borrowed
4346
--> $DIR/non-exhaustive-match.rs:46:22

src/test/ui/match/match_non_exhaustive.stderr

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ LL | match e2 { E2::A => (), E2::B => () };
3737
| ^^ pattern `_` not covered
3838
|
3939
= note: the matched value is of type `E2`, which is marked as non-exhaustive
40-
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
40+
help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
41+
|
42+
LL | match e2 { E2::A => (), E2::B => (), _ => todo!() };
43+
| ++++++++++++++
4144

4245
error: aborting due to 3 previous errors
4346

src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ LL | match Foo::A {
55
| ^^^^^^ pattern `_` not covered
66
|
77
= note: the matched value is of type `Foo`
8-
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
8+
help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
9+
|
10+
LL ~ Foo::B => {}
11+
LL + _ => todo!()
12+
|
913

1014
error[E0004]: non-exhaustive patterns: `B` not covered
1115
--> $DIR/doc-hidden-non-exhaustive.rs:14:11
@@ -19,7 +23,11 @@ LL | B,
1923
| - not covered
2024
|
2125
= note: the matched value is of type `Foo`
22-
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
26+
help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
27+
|
28+
LL ~ Foo::C => {}
29+
LL + B => todo!()
30+
|
2331

2432
error[E0004]: non-exhaustive patterns: `B` and `_` not covered
2533
--> $DIR/doc-hidden-non-exhaustive.rs:20:11
@@ -51,7 +59,11 @@ LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
5159
| ---- not covered
5260
|
5361
= note: the matched value is of type `Option<Foo>`
54-
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
62+
help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
63+
|
64+
LL ~ Some(Foo::A) => {}
65+
LL + Some(B) | Some(_) => todo!()
66+
|
5567

5668
error: aborting due to 4 previous errors
5769

src/test/ui/pattern/usefulness/guards.stderr

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ LL | match 0u8 {
55
| ^^^ pattern `128_u8..=u8::MAX` not covered
66
|
77
= note: the matched value is of type `u8`
8-
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
8+
help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
9+
|
10+
LL ~ 128 ..= 255 if true => {}
11+
LL + 128_u8..=u8::MAX => todo!()
12+
|
913

1014
error: aborting due to previous error
1115

src/test/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,11 @@ LL | match 0i8 {
9696
| ^^^ pattern `0_i8` not covered
9797
|
9898
= note: the matched value is of type `i8`
99-
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
99+
help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
100+
|
101+
LL ~ 1 ..= i8::MAX => {}
102+
LL + 0_i8 => todo!()
103+
|
100104

101105
error[E0004]: non-exhaustive patterns: `u128::MAX` not covered
102106
--> $DIR/exhaustiveness.rs:59:8
@@ -144,7 +148,11 @@ LL | match (0u8, true) {
144148
| ^^^^^^^^^^^ pattern `(126_u8..=127_u8, false)` not covered
145149
|
146150
= note: the matched value is of type `(u8, bool)`
147-
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
151+
help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
152+
|
153+
LL ~ (0 ..= 255, true) => {}
154+
LL + (126_u8..=127_u8, false) => todo!()
155+
|
148156

149157
error: aborting due to 12 previous errors
150158

src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,11 @@ LL | match 0isize {
153153
= note: the matched value is of type `isize`
154154
= note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
155155
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
156-
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
156+
help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
157+
|
158+
LL ~ 1 ..= isize::MAX => {}
159+
LL + _ => todo!()
160+
|
157161

158162
error[E0004]: non-exhaustive patterns: type `usize` is non-empty
159163
--> $DIR/pointer-sized-int.rs:48:11

src/test/ui/pattern/usefulness/issue-15129.stderr

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ LL | match (T::T1(()), V::V2(true)) {
55
| ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `(T1(()), V2(_))` and `(T2(()), V1(_))` not covered
66
|
77
= note: the matched value is of type `(T, V)`
8-
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
8+
help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
9+
|
10+
LL ~ (T::T2(()), V::V2(b)) => (),
11+
LL ~ (T1(()), V2(_)) | (T2(()), V1(_)) => todo!(),
12+
|
913

1014
error: aborting due to previous error
1115

src/test/ui/pattern/usefulness/issue-2111.stderr

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ LL | match (a, b) {
55
| ^^^^^^ patterns `(None, None)` and `(Some(_), Some(_))` not covered
66
|
77
= note: the matched value is of type `(Option<usize>, Option<usize>)`
8-
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
8+
help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
9+
|
10+
LL ~ (Some(_), None) | (None, Some(_)) => {}
11+
LL + (None, None) | (Some(_), Some(_)) => todo!()
12+
|
913

1014
error: aborting due to previous error
1115

src/test/ui/pattern/usefulness/issue-30240.stderr

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ LL | match "world" {
1818
| ^^^^^^^ pattern `&_` not covered
1919
|
2020
= note: the matched value is of type `&str`
21-
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
21+
help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
22+
|
23+
LL ~ "hello" => {}
24+
LL + &_ => todo!()
25+
|
2226

2327
error: aborting due to 2 previous errors
2428

0 commit comments

Comments
 (0)