Skip to content

Commit 76bac19

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 c947b00 commit 76bac19

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
@@ -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

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

692716
// 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
@@ -3176,13 +3176,13 @@ impl<'a> Parser<'a> {
31763176
arm_body = Some(expr);
31773177
// Eat a comma if it exists, though.
31783178
let _ = this.eat(exp!(Comma));
3179-
comma = Some(this.prev_token.span);
31803179
Ok(Recovered::No)
31813180
} else if let Some((span, guar)) =
31823181
this.parse_arm_body_missing_braces(&expr, arrow_span)
31833182
{
31843183
let body = this.mk_expr_err(span, guar);
31853184
arm_body = Some(body);
3185+
let _ = this.eat(exp!(Comma));
31863186
Ok(Recovered::Yes(guar))
31873187
} else {
31883188
let expr_span = expr.span;
@@ -3223,6 +3223,9 @@ impl<'a> Parser<'a> {
32233223
})
32243224
}
32253225
};
3226+
if let TokenKind::Comma = this.prev_token.kind {
3227+
comma = Some(this.prev_token.span);
3228+
}
32263229

32273230
let hi_span =
32283231
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)