Skip to content

Commit d112fca

Browse files
committed
Fix incorrect suggestion for never patterns with bodies or guard
When encountering an unreachable match arm, (correctly) suggest removing the entire arm: ``` error: a never pattern is always unreachable --> $DIR/ICE-130779-never-arm-no-oatherwise-block.rs:10:20 | LL | ! if true => {} | ^^ this will never be executed | help: remove the unreachable match arm | LL - ! if true => {} | ``` Noticed in #137343 (comment).
1 parent 0ad983b commit d112fca

27 files changed

+137
-77
lines changed

compiler/rustc_ast_lowering/messages.ftl

+2-2
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,11 @@ ast_lowering_misplaced_relax_trait_bound =
133133
ast_lowering_never_pattern_with_body =
134134
a never pattern is always unreachable
135135
.label = this will never be executed
136-
.suggestion = remove this expression
136+
.suggestion = remove the unreachable match arm
137137
138138
ast_lowering_never_pattern_with_guard =
139139
a guard on a never pattern will never be run
140-
.suggestion = remove this guard
140+
.suggestion = remove the unreachable match arm
141141
142142
ast_lowering_no_precise_captures_on_apit = `use<...>` precise capturing syntax not allowed in argument-position `impl Trait`
143143

compiler/rustc_ast_lowering/src/errors.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ pub(crate) struct MisplacedRelaxTraitBound {
335335
pub(crate) struct MatchArmWithNoBody {
336336
#[primary_span]
337337
pub span: Span,
338-
#[suggestion(code = " => todo!(),", applicability = "has-placeholders")]
338+
#[suggestion(code = " => todo!(),", applicability = "has-placeholders", style = "verbose")]
339339
pub suggestion: Span,
340340
}
341341

@@ -344,16 +344,18 @@ pub(crate) struct MatchArmWithNoBody {
344344
pub(crate) struct NeverPatternWithBody {
345345
#[primary_span]
346346
#[label]
347-
#[suggestion(code = "", applicability = "maybe-incorrect")]
348347
pub span: Span,
348+
#[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")]
349+
pub removal_span: Span,
349350
}
350351

351352
#[derive(Diagnostic)]
352353
#[diag(ast_lowering_never_pattern_with_guard)]
353354
pub(crate) struct NeverPatternWithGuard {
354355
#[primary_span]
355-
#[suggestion(code = "", applicability = "maybe-incorrect")]
356356
pub span: Span,
357+
#[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")]
358+
pub removal_span: Span,
357359
}
358360

359361
#[derive(Diagnostic)]

compiler/rustc_ast_lowering/src/expr.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -685,9 +685,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
685685
self.dcx().emit_err(MatchArmWithNoBody { span, suggestion });
686686
}
687687
} else if let Some(body) = &arm.body {
688-
self.dcx().emit_err(NeverPatternWithBody { span: body.span });
688+
self.dcx()
689+
.emit_err(NeverPatternWithBody { span: body.span, removal_span: arm.span });
689690
} else if let Some(g) = &arm.guard {
690-
self.dcx().emit_err(NeverPatternWithGuard { span: g.span });
691+
self.dcx().emit_err(NeverPatternWithGuard { span: g.span, removal_span: arm.span });
691692
}
692693

693694
// We add a fake `loop {}` arm body so that it typecks to `!`. The mir lowering of never

compiler/rustc_parse/src/parser/expr.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -3175,13 +3175,13 @@ impl<'a> Parser<'a> {
31753175
arm_body = Some(expr);
31763176
// Eat a comma if it exists, though.
31773177
let _ = this.eat(exp!(Comma));
3178-
comma = Some(this.prev_token.span);
31793178
Ok(Recovered::No)
31803179
} else if let Some((span, guar)) =
31813180
this.parse_arm_body_missing_braces(&expr, arrow_span)
31823181
{
31833182
let body = this.mk_expr_err(span, guar);
31843183
arm_body = Some(body);
3184+
let _ = this.eat(exp!(Comma));
31853185
Ok(Recovered::Yes(guar))
31863186
} else {
31873187
let expr_span = expr.span;
@@ -3222,6 +3222,9 @@ impl<'a> Parser<'a> {
32223222
})
32233223
}
32243224
};
3225+
if let TokenKind::Comma = this.prev_token.kind {
3226+
comma = Some(this.prev_token.span);
3227+
}
32253228

32263229
let hi_span =
32273230
comma.unwrap_or(arm_body.as_ref().map_or(span_before_body, |body| body.span));

tests/ui/attributes/collapse-debuginfo-invalid.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ LL | #[collapse_debuginfo(yes)]
7676
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
7777
LL |
7878
LL | _ => (),
79-
| ------- not a macro definition
79+
| -------- not a macro definition
8080

8181
error: `collapse_debuginfo` attribute should be applied to macro definitions
8282
--> $DIR/collapse-debuginfo-invalid.rs:40:1

tests/ui/closures/2229_closure_analysis/match/issue-88331.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ LL | pub struct Opcode(pub u8);
1313
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
1414
|
1515
LL ~ Opcode::OP1 => unimplemented!(),
16-
LL ~ Opcode(0_u8) | Opcode(2_u8..=u8::MAX) => todo!(),
16+
LL + Opcode(0_u8) | Opcode(2_u8..=u8::MAX) => todo!()
1717
|
1818

1919
error[E0004]: non-exhaustive patterns: `Opcode2(Opcode(0_u8))` and `Opcode2(Opcode(2_u8..=u8::MAX))` not covered
@@ -31,7 +31,7 @@ LL | pub struct Opcode2(Opcode);
3131
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
3232
|
3333
LL ~ Opcode2::OP2=> unimplemented!(),
34-
LL ~ Opcode2(Opcode(0_u8)) | Opcode2(Opcode(2_u8..=u8::MAX)) => todo!(),
34+
LL + Opcode2(Opcode(0_u8)) | Opcode2(Opcode(2_u8..=u8::MAX)) => todo!()
3535
|
3636

3737
error: aborting due to 2 previous errors

tests/ui/coverage-attr/allowed-positions.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ error[E0788]: coverage attribute not allowed here
8282
LL | #[coverage(off)]
8383
| ^^^^^^^^^^^^^^^^
8484
LL | () => (),
85-
| -------- not a function, impl block, or module
85+
| --------- not a function, impl block, or module
8686
|
8787
= help: coverage attribute can be applied to a function (with body), impl block, or module
8888

tests/ui/feature-gates/feature-gate-never_patterns.stderr

+6-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,12 @@ error: a guard on a never pattern will never be run
108108
--> $DIR/feature-gate-never_patterns.rs:54:19
109109
|
110110
LL | Err(!) if false,
111-
| ^^^^^ help: remove this guard
111+
| ^^^^^
112+
|
113+
help: remove the unreachable match arm
114+
|
115+
LL - Err(!) if false,
116+
|
112117

113118
error: aborting due to 13 previous errors
114119

tests/ui/force-inlining/invalid.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ LL | #[rustc_force_inline]
316316
| ^^^^^^^^^^^^^^^^^^^^^
317317
LL |
318318
LL | 1 => (),
319-
| ------- not a function definition
319+
| -------- not a function definition
320320

321321
error: attribute should be applied to a function
322322
--> $DIR/invalid.rs:98:5

tests/ui/pattern/usefulness/issue-15129.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ LL | match (T::T1(()), V::V2(true)) {
88
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
99
|
1010
LL ~ (T::T2(()), V::V2(b)) => (),
11-
LL ~ (T::T1(()), V::V2(_)) | (T::T2(()), V::V1(_)) => todo!(),
11+
LL + (T::T1(()), V::V2(_)) | (T::T2(()), V::V1(_)) => todo!()
1212
|
1313

1414
error: aborting due to 1 previous error

tests/ui/pattern/usefulness/issue-3601.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ note: `Box<ElementKind>` defined here
1111
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
1212
|
1313
LL ~ box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => true,
14-
LL ~ box ElementKind::HTMLImageElement(_) => todo!(),
14+
LL + box ElementKind::HTMLImageElement(_) => todo!()
1515
|
1616

1717
error: aborting due to 1 previous error

tests/ui/pattern/usefulness/issue-39362.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ LL | Bar { bar: Bar, id: usize }
1515
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
1616
|
1717
LL ~ Foo::Bar { bar: Bar::B, .. } => (),
18-
LL ~ _ => todo!(),
18+
LL + _ => todo!()
1919
|
2020

2121
error: aborting due to 1 previous error

tests/ui/pattern/usefulness/issue-40221.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ LL | C(PC),
1515
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
1616
|
1717
LL ~ P::C(PC::Q) => (),
18-
LL ~ P::C(PC::QA) => todo!(),
18+
LL + P::C(PC::QA) => todo!()
1919
|
2020

2121
error: aborting due to 1 previous error

tests/ui/pattern/usefulness/issue-72377.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ LL | match (x, y) {
88
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
99
|
1010
LL ~ (X::A, Some(X::C)) | (X::C, Some(X::A)) => false,
11-
LL ~ _ => todo!(),
11+
LL + _ => todo!()
1212
|
1313

1414
error: aborting due to 1 previous error

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

+8-8
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | match 0 {
99
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
1010
|
1111
LL ~ 1..=usize::MAX => (),
12-
LL ~ usize::MAX.. => todo!(),
12+
LL + usize::MAX.. => todo!()
1313
|
1414

1515
error[E0004]: non-exhaustive patterns: `(usize::MAX.., _)` not covered
@@ -23,7 +23,7 @@ LL | match (0usize, 0usize) {
2323
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
2424
|
2525
LL ~ (1..=usize::MAX, 1..=usize::MAX) => (),
26-
LL ~ (usize::MAX.., _) => todo!(),
26+
LL + (usize::MAX.., _) => todo!()
2727
|
2828

2929
error[E0004]: non-exhaustive patterns: `(..isize::MIN, _)` and `(isize::MAX.., _)` not covered
@@ -37,7 +37,7 @@ LL | match (0isize, 0usize) {
3737
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
3838
|
3939
LL ~ (isize::MIN..=isize::MAX, 1..=usize::MAX) => (),
40-
LL ~ (..isize::MIN, _) | (isize::MAX.., _) => todo!(),
40+
LL + (..isize::MIN, _) | (isize::MAX.., _) => todo!()
4141
|
4242

4343
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
@@ -74,7 +74,7 @@ note: `Option<usize>` defined here
7474
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
7575
|
7676
LL ~ None => (),
77-
LL ~ Some(usize::MAX..) => todo!(),
77+
LL + Some(usize::MAX..) => todo!()
7878
|
7979

8080
error[E0004]: non-exhaustive patterns: `Some(Some(Some(usize::MAX..)))` not covered
@@ -97,7 +97,7 @@ note: `Option<Option<Option<usize>>>` defined here
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 ~ None => (),
100-
LL ~ Some(Some(Some(usize::MAX..))) => todo!(),
100+
LL + Some(Some(Some(usize::MAX..))) => todo!()
101101
|
102102

103103
error[E0004]: non-exhaustive patterns: `A { a: usize::MAX.. }` not covered
@@ -116,7 +116,7 @@ LL | struct A<T> {
116116
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
117117
|
118118
LL ~ A { a: 1..=usize::MAX } => (),
119-
LL ~ A { a: usize::MAX.. } => todo!(),
119+
LL + A { a: usize::MAX.. } => todo!()
120120
|
121121

122122
error[E0004]: non-exhaustive patterns: `B(..isize::MIN, _)` and `B(isize::MAX.., _)` not covered
@@ -135,7 +135,7 @@ LL | struct B<T, U>(T, U);
135135
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
136136
|
137137
LL ~ B(isize::MIN..=isize::MAX, 1..=usize::MAX) => (),
138-
LL ~ B(..isize::MIN, _) | B(isize::MAX.., _) => todo!(),
138+
LL + B(..isize::MIN, _) | B(isize::MAX.., _) => todo!()
139139
|
140140

141141
error[E0004]: non-exhaustive patterns: `B(_, usize::MAX..)` not covered
@@ -154,7 +154,7 @@ LL | struct B<T, U>(T, U);
154154
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
155155
|
156156
LL ~ B(_, 1..=usize::MAX) => (),
157-
LL ~ B(_, usize::MAX..) => todo!(),
157+
LL + B(_, usize::MAX..) => todo!()
158158
|
159159

160160
error: aborting due to 9 previous errors

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

+7-7
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ LL | struct Foo {
1313
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
1414
|
1515
LL ~ Foo { first: false, second: Some([1, 2, 3, 4]) } => (),
16-
LL ~ Foo { first: false, second: Some([0_usize, _, _, _]) } | Foo { first: false, second: Some([2_usize.., _, _, _]) } => todo!(),
16+
LL + Foo { first: false, second: Some([0_usize, _, _, _]) } | Foo { first: false, second: Some([2_usize.., _, _, _]) } => todo!()
1717
|
1818

1919
error[E0004]: non-exhaustive patterns: `Color::Red` not covered
@@ -33,7 +33,7 @@ LL | Red,
3333
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
3434
|
3535
LL ~ Color::Green => (),
36-
LL ~ Color::Red => todo!(),
36+
LL + Color::Red => todo!()
3737
|
3838

3939
error[E0004]: non-exhaustive patterns: `Direction::East`, `Direction::South` and `Direction::West` not covered
@@ -58,7 +58,7 @@ LL | West,
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
@@ -87,7 +87,7 @@ LL | Sixth,
8787
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
8888
|
8989
LL ~ ExcessiveEnum::First => (),
90-
LL ~ _ => todo!(),
90+
LL + _ => todo!()
9191
|
9292

9393
error[E0004]: non-exhaustive patterns: `Color::CustomRGBA { a: true, .. }` not covered
@@ -108,7 +108,7 @@ LL | CustomRGBA { a: bool, r: u8, g: u8, b: u8 },
108108
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
109109
|
110110
LL ~ Color::CustomRGBA { a: false, r: _, g: _, b: _ } => (),
111-
LL ~ Color::CustomRGBA { a: true, .. } => todo!(),
111+
LL + Color::CustomRGBA { a: true, .. } => todo!()
112112
|
113113

114114
error[E0004]: non-exhaustive patterns: `[Enum::Second(true), Enum::Second(false)]` not covered
@@ -121,7 +121,7 @@ LL | match *x {
121121
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
122122
|
123123
LL ~ [_, _, ref tail @ .., _] => (),
124-
LL ~ [Enum::Second(true), Enum::Second(false)] => todo!(),
124+
LL + [Enum::Second(true), Enum::Second(false)] => todo!()
125125
|
126126

127127
error[E0004]: non-exhaustive patterns: `((), false)` not covered
@@ -134,7 +134,7 @@ LL | match ((), false) {
134134
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
135135
|
136136
LL ~ ((), true) => (),
137-
LL ~ ((), false) => todo!(),
137+
LL + ((), false) => todo!()
138138
|
139139

140140
error: aborting due to 7 previous errors

tests/ui/pattern/usefulness/slice_of_empty.exhaustive_patterns.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ LL | match nevers {
88
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
99
|
1010
LL ~ &[_] => (),
11-
LL ~ &[] => todo!(),
11+
LL + &[] => todo!()
1212
|
1313

1414
error: aborting due to 1 previous error

tests/ui/pattern/usefulness/slice_of_empty.normal.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | match nevers {
99
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
1010
|
1111
LL ~ &[] => (),
12-
LL ~ &[_, ..] => todo!(),
12+
LL + &[_, ..] => todo!()
1313
|
1414

1515
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
@@ -22,7 +22,7 @@ LL | match nevers {
2222
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
2323
|
2424
LL ~ &[_] => (),
25-
LL ~ &[] | &[_, _, ..] => todo!(),
25+
LL + &[] | &[_, _, ..] => todo!()
2626
|
2727

2828
error: aborting due to 2 previous errors

tests/ui/pattern/usefulness/type_polymorphic_byte_str_literals.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ LL | match data {
88
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
99
|
1010
LL ~ b"" => 1,
11-
LL ~ &[_, ..] => todo!(),
11+
LL + &[_, ..] => todo!()
1212
|
1313

1414
error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 1 more not covered
@@ -21,7 +21,7 @@ LL | match data {
2121
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
2222
|
2323
LL ~ [_, _, _] => 1,
24-
LL ~ _ => todo!(),
24+
LL + _ => todo!()
2525
|
2626

2727
error: aborting due to 2 previous errors

tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.stderr

+10-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,16 @@ error: a guard on a never pattern will never be run
2222
--> $DIR/ICE-119271-never-arm-attr-in-guard.rs:8:13
2323
|
2424
LL | false
25-
| ^^^^^ help: remove this guard
25+
| ^^^^^
26+
|
27+
help: remove the unreachable match arm
28+
|
29+
LL - Some(!)
30+
LL -
31+
LL - if #[deny(unused_mut)]
32+
LL - false
33+
LL +
34+
|
2635

2736
error: mismatched types
2837
--> $DIR/ICE-119271-never-arm-attr-in-guard.rs:5:14

0 commit comments

Comments
 (0)