Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
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 |         Some(!) if true => {}
   |                            ^^ this will never be executed
   |
help: remove the unreachable match arm
   |
LL -         Some(!) if true => {}
LL +         Some(!),
   |
```

Noticed in #137343 (comment).
  • Loading branch information
estebank committed Mar 1, 2025
commit 49e776a80e033ddb5afdae300b99135b4c2dd6c3
4 changes: 2 additions & 2 deletions compiler/rustc_ast_lowering/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,11 @@ ast_lowering_misplaced_relax_trait_bound =
ast_lowering_never_pattern_with_body =
a never pattern is always unreachable
.label = this will never be executed
.suggestion = remove this expression
.suggestion = remove the match arm expression

ast_lowering_never_pattern_with_guard =
a guard on a never pattern will never be run
.suggestion = remove this guard
.suggestion = remove the match arm guard

ast_lowering_no_precise_captures_on_apit = `use<...>` precise capturing syntax not allowed in argument-position `impl Trait`

Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_ast_lowering/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ pub(crate) struct MisplacedRelaxTraitBound {
pub(crate) struct MatchArmWithNoBody {
#[primary_span]
pub span: Span,
#[suggestion(code = " => todo!(),", applicability = "has-placeholders")]
#[suggestion(code = " => todo!(),", applicability = "has-placeholders", style = "verbose")]
pub suggestion: Span,
}

Expand All @@ -345,16 +345,18 @@ pub(crate) struct MatchArmWithNoBody {
pub(crate) struct NeverPatternWithBody {
#[primary_span]
#[label]
#[suggestion(code = "", applicability = "maybe-incorrect")]
pub span: Span,
#[suggestion(code = ",", applicability = "maybe-incorrect", style = "verbose")]
pub removal_span: Span,
}

#[derive(Diagnostic)]
#[diag(ast_lowering_never_pattern_with_guard)]
pub(crate) struct NeverPatternWithGuard {
#[primary_span]
#[suggestion(code = "", applicability = "maybe-incorrect")]
pub span: Span,
#[suggestion(code = ",", applicability = "maybe-incorrect", style = "verbose")]
pub removal_span: Span,
}

#[derive(Diagnostic)]
Expand Down
28 changes: 26 additions & 2 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -687,9 +687,33 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.dcx().emit_err(MatchArmWithNoBody { span, suggestion });
}
} else if let Some(body) = &arm.body {
self.dcx().emit_err(NeverPatternWithBody { span: body.span });
self.dcx().emit_err(NeverPatternWithBody {
span: body.span,
removal_span: if pat.span.eq_ctxt(arm.span) {
// - ! => {}
// + !,
// FIXME: account for `(!|!)`, as pat.span ends *within* the parentheses.
pat.span.shrink_to_hi().with_hi(arm.span.hi())
} else {
// Subtly incorrect, but close enough if macros are involved.
// - ! => {}
// + ! => ,
body.span
},
});
} else if let Some(g) = &arm.guard {
self.dcx().emit_err(NeverPatternWithGuard { span: g.span });
self.dcx().emit_err(NeverPatternWithGuard {
span: g.span,
removal_span: if pat.span.eq_ctxt(arm.span) {
// - ! if cond,
// + !,
pat.span.shrink_to_hi().with_hi(arm.span.hi())
} else {
// We have something like `never!() if cond =>`
// We just remove ^^^^ which isn't entirely correct.
g.span
},
});
}

// We add a fake `loop {}` arm body so that it typecks to `!`. The mir lowering of never
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3138,13 +3138,13 @@ impl<'a> Parser<'a> {
arm_body = Some(expr);
// Eat a comma if it exists, though.
let _ = this.eat(exp!(Comma));
comma = Some(this.prev_token.span);
Ok(Recovered::No)
} else if let Some((span, guar)) =
this.parse_arm_body_missing_braces(&expr, arrow_span)
{
let body = this.mk_expr_err(span, guar);
arm_body = Some(body);
let _ = this.eat(exp!(Comma));
Ok(Recovered::Yes(guar))
} else {
let expr_span = expr.span;
Expand Down Expand Up @@ -3185,6 +3185,9 @@ impl<'a> Parser<'a> {
})
}
};
if let TokenKind::Comma = this.prev_token.kind {
comma = Some(this.prev_token.span);
}

let hi_span =
comma.unwrap_or(arm_body.as_ref().map_or(span_before_body, |body| body.span));
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/attributes/collapse-debuginfo-invalid.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ LL | #[collapse_debuginfo(yes)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | _ => (),
| ------- not a macro definition
| -------- not a macro definition

error: `collapse_debuginfo` attribute should be applied to macro definitions
--> $DIR/collapse-debuginfo-invalid.rs:40:1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ LL | pub struct Opcode(pub u8);
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 ~ Opcode::OP1 => unimplemented!(),
LL ~ Opcode(0_u8) | Opcode(2_u8..=u8::MAX) => todo!(),
LL + Opcode(0_u8) | Opcode(2_u8..=u8::MAX) => todo!()
|

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

error: aborting due to 2 previous errors
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/coverage-attr/allowed-positions.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ error[E0788]: coverage attribute not allowed here
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
LL | () => (),
| -------- not a function, impl block, or module
| --------- not a function, impl block, or module
|
= help: coverage attribute can be applied to a function (with body), impl block, or module

Expand Down
8 changes: 7 additions & 1 deletion tests/ui/feature-gates/feature-gate-never_patterns.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,13 @@ error: a guard on a never pattern will never be run
--> $DIR/feature-gate-never_patterns.rs:54:19
|
LL | Err(!) if false,
| ^^^^^ help: remove this guard
| ^^^^^
|
help: remove the match arm guard
|
LL - Err(!) if false,
LL + Err(!),
|

error: aborting due to 13 previous errors

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/force-inlining/invalid.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ LL | #[rustc_force_inline]
| ^^^^^^^^^^^^^^^^^^^^^
LL |
LL | 1 => (),
| ------- not a function definition
| -------- not a function definition

error: attribute should be applied to a function
--> $DIR/invalid.rs:98:5
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/pattern/usefulness/issue-15129.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ LL | match (T::T1(()), V::V2(true)) {
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 ~ (T::T2(()), V::V2(b)) => (),
LL ~ (T::T1(()), V::V2(_)) | (T::T2(()), V::V1(_)) => todo!(),
LL + (T::T1(()), V::V2(_)) | (T::T2(()), V::V1(_)) => todo!()
|

error: aborting due to 1 previous error
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/pattern/usefulness/issue-3601.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
|
LL ~ box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => true,
LL ~ box ElementKind::HTMLImageElement(_) => todo!(),
LL + box ElementKind::HTMLImageElement(_) => todo!()
|

error: aborting due to 1 previous error
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/pattern/usefulness/issue-39362.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ LL | Bar { bar: Bar, id: usize }
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
|
LL ~ Foo::Bar { bar: Bar::B, .. } => (),
LL ~ _ => todo!(),
LL + _ => todo!()
|

error: aborting due to 1 previous error
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/pattern/usefulness/issue-40221.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ LL | C(PC),
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 ~ P::C(PC::Q) => (),
LL ~ P::C(PC::QA) => todo!(),
LL + P::C(PC::QA) => todo!()
|

error: aborting due to 1 previous error
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/pattern/usefulness/issue-72377.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ LL | match (x, y) {
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
|
LL ~ (X::A, Some(X::C)) | (X::C, Some(X::A)) => false,
LL ~ _ => todo!(),
LL + _ => todo!()
|

error: aborting due to 1 previous error
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ LL | match 0 {
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 ~ 1..=usize::MAX => (),
LL ~ usize::MAX.. => todo!(),
LL + usize::MAX.. => todo!()
|

error[E0004]: non-exhaustive patterns: `(usize::MAX.., _)` not covered
Expand All @@ -23,7 +23,7 @@ LL | match (0usize, 0usize) {
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 ~ (1..=usize::MAX, 1..=usize::MAX) => (),
LL ~ (usize::MAX.., _) => todo!(),
LL + (usize::MAX.., _) => todo!()
|

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

error[E0004]: non-exhaustive patterns: `Some(_)` not covered
Expand Down Expand Up @@ -74,7 +74,7 @@ note: `Option<usize>` 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
|
LL ~ None => (),
LL ~ Some(usize::MAX..) => todo!(),
LL + Some(usize::MAX..) => todo!()
|

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

error[E0004]: non-exhaustive patterns: `A { a: usize::MAX.. }` not covered
Expand All @@ -116,7 +116,7 @@ LL | struct A<T> {
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 ~ A { a: 1..=usize::MAX } => (),
LL ~ A { a: usize::MAX.. } => todo!(),
LL + A { a: usize::MAX.. } => todo!()
|

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

error[E0004]: non-exhaustive patterns: `B(_, usize::MAX..)` not covered
Expand All @@ -154,7 +154,7 @@ LL | struct B<T, U>(T, U);
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 ~ B(_, 1..=usize::MAX) => (),
LL ~ B(_, usize::MAX..) => todo!(),
LL + B(_, usize::MAX..) => todo!()
|

error: aborting due to 9 previous errors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ LL | struct Foo {
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 ~ Foo { first: false, second: Some([1, 2, 3, 4]) } => (),
LL ~ Foo { first: false, second: Some([0_usize, _, _, _]) } | Foo { first: false, second: Some([2_usize.., _, _, _]) } => todo!(),
LL + Foo { first: false, second: Some([0_usize, _, _, _]) } | Foo { first: false, second: Some([2_usize.., _, _, _]) } => todo!()
|

error[E0004]: non-exhaustive patterns: `Color::Red` not covered
Expand All @@ -33,7 +33,7 @@ LL | Red,
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 ~ Color::Green => (),
LL ~ Color::Red => todo!(),
LL + Color::Red => todo!()
|

error[E0004]: non-exhaustive patterns: `Direction::East`, `Direction::South` and `Direction::West` not covered
Expand All @@ -58,7 +58,7 @@ LL | West,
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 ~ Direction::North => (),
LL ~ Direction::East | Direction::South | Direction::West => todo!(),
LL + Direction::East | Direction::South | Direction::West => todo!()
|

error[E0004]: non-exhaustive patterns: `ExcessiveEnum::Second`, `ExcessiveEnum::Third`, `ExcessiveEnum::Fourth` and 8 more not covered
Expand Down Expand Up @@ -87,7 +87,7 @@ LL | Sixth,
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
|
LL ~ ExcessiveEnum::First => (),
LL ~ _ => todo!(),
LL + _ => todo!()
|

error[E0004]: non-exhaustive patterns: `Color::CustomRGBA { a: true, .. }` not covered
Expand All @@ -108,7 +108,7 @@ LL | CustomRGBA { a: bool, r: u8, g: u8, b: u8 },
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 ~ Color::CustomRGBA { a: false, r: _, g: _, b: _ } => (),
LL ~ Color::CustomRGBA { a: true, .. } => todo!(),
LL + Color::CustomRGBA { a: true, .. } => todo!()
|

error[E0004]: non-exhaustive patterns: `[Enum::Second(true), Enum::Second(false)]` not covered
Expand All @@ -121,7 +121,7 @@ LL | match *x {
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 ~ [_, _, ref tail @ .., _] => (),
LL ~ [Enum::Second(true), Enum::Second(false)] => todo!(),
LL + [Enum::Second(true), Enum::Second(false)] => todo!()
|

error[E0004]: non-exhaustive patterns: `((), false)` not covered
Expand All @@ -134,7 +134,7 @@ LL | match ((), false) {
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 ~ ((), true) => (),
LL ~ ((), false) => todo!(),
LL + ((), false) => todo!()
|

error: aborting due to 7 previous errors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ LL | match nevers {
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 ~ &[_] => (),
LL ~ &[] => todo!(),
LL + &[] => todo!()
|

error: aborting due to 1 previous error
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/pattern/usefulness/slice_of_empty.normal.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ LL | match nevers {
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 ~ &[] => (),
LL ~ &[_, ..] => todo!(),
LL + &[_, ..] => todo!()
|

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

error: aborting due to 2 previous errors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ LL | match data {
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 ~ b"" => 1,
LL ~ &[_, ..] => todo!(),
LL + &[_, ..] => todo!()
|

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

error: aborting due to 2 previous errors
Expand Down
Loading