Skip to content

Commit 00150b7

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 ced1fe9 commit 00150b7

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
@@ -679,6 +679,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
679679
{
680680
body
681681
} else {
682+
let removal_span = |removal_span: Span| {
683+
// Seek upwards in the macro call sites to see if we find the place where
684+
// `pat!()` was called so that we can get the right span to remove.
685+
let Some(pat_span) = pat.span.find_ancestor_in_same_ctxt(arm.span) else {
686+
return removal_span;
687+
};
688+
// - pat!() => {}
689+
// + pat!(),
690+
pat_span.shrink_to_hi().with_hi(arm.span.hi())
691+
};
682692
// Either `body.is_none()` or `is_never_pattern` here.
683693
if !is_never_pattern {
684694
if self.tcx.features().never_patterns() {
@@ -689,29 +699,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
689699
} else if let Some(body) = &arm.body {
690700
self.dcx().emit_err(NeverPatternWithBody {
691701
span: body.span,
692-
removal_span: if pat.span.eq_ctxt(arm.span) {
693-
// - ! => {}
694-
// + !,
695-
pat.span.shrink_to_hi().with_hi(arm.span.hi())
696-
} else {
697-
// Subtly incorrect, but close enough if macros are involved.
698-
// - ! => {}
699-
// + ! => ,
700-
body.span
701-
},
702+
removal_span: removal_span(body.span),
702703
});
703704
} else if let Some(g) = &arm.guard {
704705
self.dcx().emit_err(NeverPatternWithGuard {
705706
span: g.span,
706-
removal_span: if pat.span.eq_ctxt(arm.span) {
707-
// - ! if cond,
708-
// + !,
709-
pat.span.shrink_to_hi().with_hi(arm.span.hi())
710-
} else {
711-
// We have something like `never!() if cond =>`
712-
// We just remove ^^^^ which isn't entirely correct.
713-
g.span
714-
},
707+
removal_span: removal_span(g.span),
715708
});
716709
}
717710

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)