Skip to content

Commit 49e776a

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 | Some(!) if true => {} | ^^ this will never be executed | help: remove the unreachable match arm | LL - Some(!) if true => {} LL + Some(!), | ``` Noticed in rust-lang#137343 (comment).
1 parent 5d45d1e commit 49e776a

29 files changed

+213
-84
lines changed

compiler/rustc_ast_lowering/messages.ftl

Lines changed: 2 additions & 2 deletions
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 match arm expression
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 match arm guard
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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ pub(crate) struct MisplacedRelaxTraitBound {
336336
pub(crate) struct MatchArmWithNoBody {
337337
#[primary_span]
338338
pub span: Span,
339-
#[suggestion(code = " => todo!(),", applicability = "has-placeholders")]
339+
#[suggestion(code = " => todo!(),", applicability = "has-placeholders", style = "verbose")]
340340
pub suggestion: Span,
341341
}
342342

@@ -345,16 +345,18 @@ pub(crate) struct MatchArmWithNoBody {
345345
pub(crate) struct NeverPatternWithBody {
346346
#[primary_span]
347347
#[label]
348-
#[suggestion(code = "", applicability = "maybe-incorrect")]
349348
pub span: Span,
349+
#[suggestion(code = ",", applicability = "maybe-incorrect", style = "verbose")]
350+
pub removal_span: Span,
350351
}
351352

352353
#[derive(Diagnostic)]
353354
#[diag(ast_lowering_never_pattern_with_guard)]
354355
pub(crate) struct NeverPatternWithGuard {
355356
#[primary_span]
356-
#[suggestion(code = "", applicability = "maybe-incorrect")]
357357
pub span: Span,
358+
#[suggestion(code = ",", applicability = "maybe-incorrect", style = "verbose")]
359+
pub removal_span: Span,
358360
}
359361

360362
#[derive(Diagnostic)]

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -687,9 +687,33 @@ impl<'hir> LoweringContext<'_, 'hir> {
687687
self.dcx().emit_err(MatchArmWithNoBody { span, suggestion });
688688
}
689689
} else if let Some(body) = &arm.body {
690-
self.dcx().emit_err(NeverPatternWithBody { span: body.span });
690+
self.dcx().emit_err(NeverPatternWithBody {
691+
span: body.span,
692+
removal_span: if pat.span.eq_ctxt(arm.span) {
693+
// - ! => {}
694+
// + !,
695+
// FIXME: account for `(!|!)`, as pat.span ends *within* the parentheses.
696+
pat.span.shrink_to_hi().with_hi(arm.span.hi())
697+
} else {
698+
// Subtly incorrect, but close enough if macros are involved.
699+
// - ! => {}
700+
// + ! => ,
701+
body.span
702+
},
703+
});
691704
} else if let Some(g) = &arm.guard {
692-
self.dcx().emit_err(NeverPatternWithGuard { span: g.span });
705+
self.dcx().emit_err(NeverPatternWithGuard {
706+
span: g.span,
707+
removal_span: if pat.span.eq_ctxt(arm.span) {
708+
// - ! if cond,
709+
// + !,
710+
pat.span.shrink_to_hi().with_hi(arm.span.hi())
711+
} else {
712+
// We have something like `never!() if cond =>`
713+
// We just remove ^^^^ which isn't entirely correct.
714+
g.span
715+
},
716+
});
693717
}
694718

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

compiler/rustc_parse/src/parser/expr.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3138,13 +3138,13 @@ impl<'a> Parser<'a> {
31383138
arm_body = Some(expr);
31393139
// Eat a comma if it exists, though.
31403140
let _ = this.eat(exp!(Comma));
3141-
comma = Some(this.prev_token.span);
31423141
Ok(Recovered::No)
31433142
} else if let Some((span, guar)) =
31443143
this.parse_arm_body_missing_braces(&expr, arrow_span)
31453144
{
31463145
let body = this.mk_expr_err(span, guar);
31473146
arm_body = Some(body);
3147+
let _ = this.eat(exp!(Comma));
31483148
Ok(Recovered::Yes(guar))
31493149
} else {
31503150
let expr_span = expr.span;
@@ -3185,6 +3185,9 @@ impl<'a> Parser<'a> {
31853185
})
31863186
}
31873187
};
3188+
if let TokenKind::Comma = this.prev_token.kind {
3189+
comma = Some(this.prev_token.span);
3190+
}
31883191

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

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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,13 @@ error: a guard on a never pattern will never be run
133133
--> $DIR/feature-gate-never_patterns.rs:54:19
134134
|
135135
LL | Err(!) if false,
136-
| ^^^^^ help: remove this guard
136+
| ^^^^^
137+
|
138+
help: remove the match arm guard
139+
|
140+
LL - Err(!) if false,
141+
LL + Err(!),
142+
|
137143

138144
error: aborting due to 13 previous errors
139145

tests/ui/force-inlining/invalid.stderr

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

0 commit comments

Comments
 (0)