diff --git a/clippy_lints/src/matches/collapsible_match.rs b/clippy_lints/src/matches/collapsible_match.rs
index 2eb15928f25a..344e68a6df8f 100644
--- a/clippy_lints/src/matches/collapsible_match.rs
+++ b/clippy_lints/src/matches/collapsible_match.rs
@@ -165,11 +165,21 @@ fn check_arm<'tcx>(
let (paren_start, inner_if_span, paren_end) = peel_parens(cx, inner_expr.span);
let inner_if = inner_if_span.split_at(2).0;
let mut sugg = vec![(inner.then.span.shrink_to_lo(), "=> ".to_string())];
+
if matches!(outer_then_body.kind, ExprKind::Block(..)) {
- let outer_then_open_bracket = outer_then_body
- .span
- .split_at(1)
- .0
+ let block_span = outer_then_body.span;
+ // The Block Span can start with a label so finding actual opening braces instead of assuming it's
+ // first Byte
+ let block_snippet = snippet(cx, block_span, "");
+ let Some(brace_offset) = block_snippet.find('{') else {
+ return;
+ };
+ let brace_pos = block_span.lo() + BytePos(u32::try_from(brace_offset).unwrap());
+
+ let label_prefix = block_snippet[..brace_offset].trim();
+ let outer_then_open_bracket = block_span
+ .with_lo(brace_pos)
+ .with_hi(brace_pos + BytePos(1))
.with_leading_whitespace(cx)
.into_span();
let outer_then_closing_bracket = {
@@ -180,6 +190,10 @@ fn check_arm<'tcx>(
};
sugg.push((outer_arrow_end.to(outer_then_open_bracket), String::new()));
sugg.push((outer_then_closing_bracket, String::new()));
+
+ if !label_prefix.is_empty() {
+ sugg[0].1 = format!("=> {label_prefix} ");
+ }
} else {
sugg.push((outer_arrow_end.until(inner_if), " ".to_string()));
}
diff --git a/tests/ui/collapsible_match_fixable.fixed b/tests/ui/collapsible_match_fixable.fixed
index 671a785abdbe..2e34d0564f02 100644
--- a/tests/ui/collapsible_match_fixable.fixed
+++ b/tests/ui/collapsible_match_fixable.fixed
@@ -75,3 +75,20 @@ fn issue16894() {
//~^ collapsible_match
};
}
+
+// https://github.com/rust-lang/rust-clippy/issues/17427
+// `collapsible_match` suggested wrong spans when the outer arm's block has a
+// label, deleting the label's leading `'` instead of preserving it after `=>`.
+fn issue17427() {
+ let x: Result