Skip to content

Commit fba062b

Browse files
committed
fix(collapsible_match): exclude binding modes from struct field pattern suggestions
1 parent a212bd4 commit fba062b

File tree

3 files changed

+54
-15
lines changed

3 files changed

+54
-15
lines changed

clippy_lints/src/matches/collapsible_match.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use rustc_hir::LangItem::OptionNone;
1313
use rustc_hir::{Arm, Expr, ExprKind, HirId, Pat, PatExpr, PatExprKind, PatKind};
1414
use rustc_lint::LateContext;
1515
use rustc_span::Span;
16+
use rustc_span::symbol::Ident;
1617

1718
use super::{COLLAPSIBLE_MATCH, pat_contains_disallowed_or};
1819

@@ -70,7 +71,7 @@ fn check_arm<'tcx>(
7071
&& !pat_contains_disallowed_or(cx, inner_then_pat, msrv)
7172
// the binding must come from the pattern of the containing match arm
7273
// ..<local>.. => match <local> { .. }
73-
&& let (Some(binding_span), is_innermost_parent_pat_struct) =
74+
&& let (Some((binding_ident, binding_span)), is_innermost_parent_pat_struct) =
7475
find_pat_binding_and_is_innermost_parent_pat_struct(outer_pat, binding_id)
7576
// the "else" branches must be equal
7677
&& match (outer_else_body, inner_else_body) {
@@ -103,7 +104,7 @@ fn check_arm<'tcx>(
103104
// collapsing patterns need an explicit field name in struct pattern matching
104105
// ex: Struct {x: Some(1)}
105106
let replace_msg = if is_innermost_parent_pat_struct {
106-
format!(", prefixed by `{}: `", snippet(cx, binding_span, "their field name"))
107+
format!(", prefixed by `{binding_ident}: `")
107108
} else {
108109
String::new()
109110
};
@@ -140,16 +141,16 @@ fn arm_is_wild_like(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
140141
}
141142
}
142143

143-
fn find_pat_binding_and_is_innermost_parent_pat_struct(pat: &Pat<'_>, hir_id: HirId) -> (Option<Span>, bool) {
144-
let mut span = None;
144+
fn find_pat_binding_and_is_innermost_parent_pat_struct(pat: &Pat<'_>, hir_id: HirId) -> (Option<(Ident, Span)>, bool) {
145+
let mut binding = None;
145146
let mut is_innermost_parent_pat_struct = false;
146-
pat.walk_short(|p| match &p.kind {
147+
pat.walk_short(|p| match p.kind {
147148
// ignore OR patterns
148149
PatKind::Or(_) => false,
149-
PatKind::Binding(_bm, _, _ident, _) => {
150+
PatKind::Binding(_bm, _, ident, _) => {
150151
let found = p.hir_id == hir_id;
151152
if found {
152-
span = Some(p.span);
153+
binding = Some((ident, p.span));
153154
}
154155
!found
155156
},
@@ -158,7 +159,7 @@ fn find_pat_binding_and_is_innermost_parent_pat_struct(pat: &Pat<'_>, hir_id: Hi
158159
true
159160
},
160161
});
161-
(span, is_innermost_parent_pat_struct)
162+
(binding, is_innermost_parent_pat_struct)
162163
}
163164

164165
/// Builds a chain of reference-manipulation method calls (e.g., `.as_ref()`, `.as_mut()`,

tests/ui/collapsible_match.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,27 @@ pub fn test_2(x: Issue9647) {
304304
}
305305
}
306306

307+
mod issue_13287 {
308+
enum Token {
309+
Name,
310+
Other,
311+
}
312+
313+
struct Error {
314+
location: u32,
315+
token: Option<Token>,
316+
}
317+
318+
fn struct_field_pat_with_binding_mode(err: Option<Error>) {
319+
if let Some(Error { ref token, .. }) = err {
320+
if let Some(Token::Name) = token {
321+
//~^ collapsible_match
322+
println!("token used as a ref");
323+
}
324+
}
325+
}
326+
}
327+
307328
pub fn issue_14155() {
308329
let mut arr = ["a", "b", "c"];
309330
if let Some(last) = arr.last() {

tests/ui/collapsible_match.stderr

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,25 @@ LL | if let Issue9647::A { a: Some(a), .. } = x {
250250
LL | if let Some(u) = a {
251251
| ^^^^^^^ with this pattern
252252

253+
error: this `if let` can be collapsed into the outer `if let`
254+
--> tests/ui/collapsible_match.rs:320:13
255+
|
256+
LL | / if let Some(Token::Name) = token {
257+
LL | |
258+
LL | | println!("token used as a ref");
259+
LL | | }
260+
| |_____________^
261+
|
262+
help: the outer pattern can be modified to include the inner pattern
263+
--> tests/ui/collapsible_match.rs:319:29
264+
|
265+
LL | if let Some(Error { ref token, .. }) = err {
266+
| ^^^^^^^^^ replace this binding
267+
LL | if let Some(Token::Name) = token {
268+
| ^^^^^^^^^^^^^^^^^ with this pattern, prefixed by `token: `
269+
253270
error: this `match` can be collapsed into the outer `if let`
254-
--> tests/ui/collapsible_match.rs:310:9
271+
--> tests/ui/collapsible_match.rs:331:9
255272
|
256273
LL | / match *last {
257274
LL | |
@@ -263,7 +280,7 @@ LL | | }
263280
| |_________^
264281
|
265282
help: the outer pattern can be modified to include the inner pattern
266-
--> tests/ui/collapsible_match.rs:309:17
283+
--> tests/ui/collapsible_match.rs:330:17
267284
|
268285
LL | if let Some(last) = arr.last() {
269286
| ^^^^ ---------- use: `arr.last().copied()`
@@ -274,7 +291,7 @@ LL | "a" | "b" => {
274291
| ^^^^^^^^^ with this pattern
275292

276293
error: this `match` can be collapsed into the outer `if let`
277-
--> tests/ui/collapsible_match.rs:320:9
294+
--> tests/ui/collapsible_match.rs:341:9
278295
|
279296
LL | / match &last {
280297
LL | |
@@ -286,7 +303,7 @@ LL | | }
286303
| |_________^
287304
|
288305
help: the outer pattern can be modified to include the inner pattern
289-
--> tests/ui/collapsible_match.rs:319:17
306+
--> tests/ui/collapsible_match.rs:340:17
290307
|
291308
LL | if let Some(last) = arr.last() {
292309
| ^^^^ ---------- use: `arr.last().as_ref()`
@@ -297,7 +314,7 @@ LL | &&"a" | &&"b" => {
297314
| ^^^^^^^^^^^^^ with this pattern
298315

299316
error: this `match` can be collapsed into the outer `if let`
300-
--> tests/ui/collapsible_match.rs:330:9
317+
--> tests/ui/collapsible_match.rs:351:9
301318
|
302319
LL | / match &mut last {
303320
LL | |
@@ -309,7 +326,7 @@ LL | | }
309326
| |_________^
310327
|
311328
help: the outer pattern can be modified to include the inner pattern
312-
--> tests/ui/collapsible_match.rs:329:17
329+
--> tests/ui/collapsible_match.rs:350:17
313330
|
314331
LL | if let Some(mut last) = arr.last_mut() {
315332
| ^^^^^^^^ -------------- use: `arr.last_mut().as_mut()`
@@ -319,5 +336,5 @@ LL | if let Some(mut last) = arr.last_mut() {
319336
LL | &mut &mut "a" | &mut &mut "b" => {
320337
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ with this pattern
321338

322-
error: aborting due to 16 previous errors
339+
error: aborting due to 17 previous errors
323340

0 commit comments

Comments
 (0)