Skip to content

Commit b2b3e2b

Browse files
committed
Fallback removal span when involving macros
``` error: a never pattern is always unreachable --> $DIR/pattern-behind-macro.rs:13:21 | LL | never!() => {} | ^^ this will never be executed | help: remove the match arm expression | LL - never!() => {} LL + never!(), | ``` Look up the macro backtrace call sites to see if we find where the macro was used as a pattern, to properly suggest removing match arm guard and body.
1 parent 2b98116 commit b2b3e2b

File tree

5 files changed

+51
-21
lines changed

5 files changed

+51
-21
lines changed

compiler/rustc_ast_lowering/src/expr.rs

+19-19
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,23 @@ impl<'hir> LoweringContext<'_, 'hir> {
676676
{
677677
self.lower_expr(body)
678678
} else {
679+
let removal_span = |mut removal_span: Span| {
680+
for data in pat.span.macro_backtrace() {
681+
// Seek upwards in the macro call sites to see if we find the place where
682+
// `pat!()` was called so that we can get the right span to remove.
683+
if arm.span.eq_ctxt(data.call_site) {
684+
// - pat!() => {}
685+
// + pat!(),
686+
removal_span = data.call_site.shrink_to_hi().with_hi(arm.span.hi())
687+
}
688+
}
689+
if arm.span.eq_ctxt(pat.span) {
690+
// - ! => {}
691+
// + !,
692+
removal_span = pat.span.shrink_to_hi().with_hi(arm.span.hi())
693+
}
694+
removal_span
695+
};
679696
// Either `body.is_none()` or `is_never_pattern` here.
680697
if !is_never_pattern {
681698
if self.tcx.features().never_patterns() {
@@ -686,29 +703,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
686703
} else if let Some(body) = &arm.body {
687704
self.dcx().emit_err(NeverPatternWithBody {
688705
span: body.span,
689-
removal_span: if pat.span.eq_ctxt(arm.span) {
690-
// - ! => {}
691-
// + !,
692-
pat.span.shrink_to_hi().with_hi(arm.span.hi())
693-
} else {
694-
// Subtly incorrect, but close enough if macros are involved.
695-
// - ! => {}
696-
// + ! => ,
697-
body.span
698-
},
706+
removal_span: removal_span(body.span),
699707
});
700708
} else if let Some(g) = &arm.guard {
701709
self.dcx().emit_err(NeverPatternWithGuard {
702710
span: g.span,
703-
removal_span: if pat.span.eq_ctxt(arm.span) {
704-
// - ! if cond,
705-
// + !,
706-
pat.span.shrink_to_hi().with_hi(arm.span.hi())
707-
} else {
708-
// We have something like `never!() if cond =>`
709-
// We just remove ^^^^ which isn't entirely correct.
710-
g.span
711-
},
711+
removal_span: removal_span(g.span),
712712
});
713713
}
714714

src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ pub(super) fn check<'tcx>(
7171
{
7272
let mut applicability = Applicability::MachineApplicable;
7373
let mut pat_snip = snippet_with_applicability(cx, pat.span, "..", &mut applicability);
74-
if matches!(pat.kind, PatKind::Or(..)) {
74+
if matches!(pat.kind, PatKind::Or(..)) && !pat_snip.starts_with("(") {
7575
pat_snip = format!("({pat_snip})").into();
7676
}
7777
let mut arg_snip = snippet_with_applicability(cx, arg_expression.span, "..", &mut applicability);

tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ LL | never!() if true,
7676
help: remove the match arm guard
7777
|
7878
LL - never!() if true,
79-
LL + never!() if ,,
79+
LL + never!(),
8080
|
8181

8282
error: aborting due to 8 previous errors
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#![feature(never_patterns, never_type)]
2+
#![allow(incomplete_features)]
3+
4+
enum Void {}
5+
fn main() {}
6+
7+
macro_rules! never {
8+
() => { ! }
9+
}
10+
11+
fn no_arms_or_guards(x: Void) {
12+
match x {
13+
never!() => {}
14+
//~^ ERROR a never pattern is always unreachable
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: a never pattern is always unreachable
2+
--> $DIR/pattern-behind-macro.rs:13:21
3+
|
4+
LL | never!() => {}
5+
| ^^ this will never be executed
6+
|
7+
help: remove the match arm expression
8+
|
9+
LL - never!() => {}
10+
LL + never!(),
11+
|
12+
13+
error: aborting due to 1 previous error
14+

0 commit comments

Comments
 (0)