Skip to content

Commit 88398eb

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 7c677f8 commit 88398eb

File tree

5 files changed

+44
-21
lines changed

5 files changed

+44
-21
lines changed

compiler/rustc_ast_lowering/src/expr.rs

+12-19
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
676676
{
677677
self.lower_expr(body)
678678
} else {
679+
let removal_span = |removal_span: Span| {
680+
// Seek upwards in the macro call sites to see if we find the place where
681+
// `pat!()` was called so that we can get the right span to remove.
682+
let Some(pat_span) = pat.span.find_ancestor_in_same_ctxt(arm.span) else {
683+
return removal_span;
684+
};
685+
// - pat!() => {}
686+
// + pat!(),
687+
pat_span.shrink_to_hi().with_hi(arm.span.hi())
688+
};
679689
// Either `body.is_none()` or `is_never_pattern` here.
680690
if !is_never_pattern {
681691
if self.tcx.features().never_patterns() {
@@ -686,29 +696,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
686696
} else if let Some(body) = &arm.body {
687697
self.dcx().emit_err(NeverPatternWithBody {
688698
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-
},
699+
removal_span: removal_span(body.span),
699700
});
700701
} else if let Some(g) = &arm.guard {
701702
self.dcx().emit_err(NeverPatternWithGuard {
702703
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-
},
704+
removal_span: removal_span(g.span),
712705
});
713706
}
714707

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)