@@ -13,7 +13,6 @@ use super::REDUNDANT_GUARDS;
13
13
14
14
pub ( super ) fn check < ' tcx > ( cx : & LateContext < ' tcx > , arms : & ' tcx [ Arm < ' tcx > ] ) {
15
15
for outer_arm in arms {
16
- let mut app = Applicability :: MaybeIncorrect ;
17
16
let Some ( guard) = outer_arm. guard else {
18
17
continue ;
19
18
} ;
@@ -34,40 +33,31 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>]) {
34
33
] ,
35
34
MatchSource :: Normal ,
36
35
) = if_expr. kind
37
- && let Some ( ( pat_binding, can_use_shorthand) ) = get_pat_binding ( cx, scrutinee, outer_arm)
38
36
{
39
37
emit_redundant_guards (
40
38
cx,
41
39
outer_arm,
42
40
if_expr. span ,
43
- pat_binding,
44
- can_use_shorthand,
41
+ scrutinee,
45
42
arm. pat . span ,
46
43
arm. guard ,
47
- & mut app,
48
44
) ;
49
45
}
50
46
// `Some(x) if let Some(2) = x`
51
- else if let Guard :: IfLet ( let_expr) = guard
52
- && let pat = let_expr. pat
53
- && let Some ( ( pat_binding, can_use_shorthand) ) = get_pat_binding ( cx, let_expr. init , outer_arm)
54
- {
47
+ else if let Guard :: IfLet ( let_expr) = guard {
55
48
emit_redundant_guards (
56
49
cx,
57
50
outer_arm,
58
51
let_expr. span ,
59
- pat_binding,
60
- can_use_shorthand,
61
- pat. span ,
52
+ let_expr. init ,
53
+ let_expr. pat . span ,
62
54
None ,
63
- & mut app,
64
55
) ;
65
56
}
66
57
// `Some(x) if x == Some(2)`
67
58
else if let Guard :: If ( if_expr) = guard
68
59
&& let ExprKind :: Binary ( bin_op, local, pat) = if_expr. kind
69
60
&& matches ! ( bin_op. node, BinOpKind :: Eq )
70
- && let Some ( ( pat_binding, can_use_shorthand) ) = get_pat_binding ( cx, local, outer_arm)
71
61
&& expr_can_be_pat ( cx, pat)
72
62
// Ensure they have the same type. If they don't, we'd need deref coercion which isn't
73
63
// possible (currently) in a pattern. In some cases, you can use something like
@@ -81,11 +71,9 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>]) {
81
71
cx,
82
72
outer_arm,
83
73
if_expr. span ,
84
- pat_binding,
85
- can_use_shorthand,
74
+ local,
86
75
pat. span ,
87
76
None ,
88
- & mut app,
89
77
) ;
90
78
}
91
79
}
@@ -94,14 +82,21 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>]) {
94
82
fn get_pat_binding < ' tcx > ( cx : & LateContext < ' tcx > , guard_expr : & Expr < ' _ > , outer_arm : & Arm < ' tcx > ) -> Option < ( Span , bool ) > {
95
83
if let Some ( local) = path_to_local ( guard_expr) && !is_local_used ( cx, outer_arm. body , local) {
96
84
let mut span = None ;
97
- // FIXME: hir_id == local is only true for the first or, this will always be false
98
85
let mut multiple_bindings = false ;
99
- outer_arm. pat . each_binding ( |_, hir_id, binding_span, _| {
100
- if hir_id == local && span. replace ( binding_span) . is_some ( ) {
86
+ // `each_binding` gives the `HirId` of the `Pat` itself, not the binding
87
+ outer_arm. pat . walk ( |pat| {
88
+ if let PatKind :: Binding ( _, hir_id, _, _) = pat. kind
89
+ && hir_id == local
90
+ && span. replace ( pat. span ) . is_some ( )
91
+ {
101
92
multiple_bindings = true ;
93
+ return false ;
102
94
}
95
+
96
+ true
103
97
} ) ;
104
98
99
+ // Ignore bindings from or patterns, like `First(x) | Second(x, _) | Third(x, _, _)`
105
100
if !multiple_bindings {
106
101
return span. map ( |span| {
107
102
(
@@ -115,35 +110,26 @@ fn get_pat_binding<'tcx>(cx: &LateContext<'tcx>, guard_expr: &Expr<'_>, outer_ar
115
110
None
116
111
}
117
112
118
- fn get_guard ( cx : & LateContext < ' _ > , guard : Option < Guard < ' _ > > , app : & mut Applicability ) -> String {
119
- guard. map_or_else ( String :: new, |guard| {
120
- let ( prefix, span) = match guard {
121
- Guard :: If ( e) => ( "if" , e. span ) ,
122
- Guard :: IfLet ( l) => ( "if let" , l. span ) ,
123
- } ;
124
-
125
- format ! ( " {prefix} {}" , snippet_with_applicability( cx, span, "<guard>" , app) )
126
- } )
127
- }
128
-
129
- #[ expect( clippy:: too_many_arguments) ]
130
- fn emit_redundant_guards (
131
- cx : & LateContext < ' _ > ,
132
- outer_arm : & Arm < ' _ > ,
113
+ fn emit_redundant_guards < ' tcx > (
114
+ cx : & LateContext < ' tcx > ,
115
+ outer_arm : & Arm < ' tcx > ,
133
116
guard_span : Span ,
134
- pat_binding : Span ,
135
- can_use_shorthand : bool ,
117
+ local : & Expr < ' _ > ,
136
118
pat_span : Span ,
137
119
inner_guard : Option < Guard < ' _ > > ,
138
- app : & mut Applicability ,
139
120
) {
121
+ let mut app = Applicability :: MaybeIncorrect ;
122
+ let Some ( ( pat_binding, can_use_shorthand) ) = get_pat_binding ( cx, local, outer_arm) else {
123
+ return ;
124
+ } ;
125
+
140
126
span_lint_and_then (
141
127
cx,
142
128
REDUNDANT_GUARDS ,
143
129
guard_span. source_callsite ( ) ,
144
130
"redundant guard" ,
145
131
|diag| {
146
- let binding_replacement = snippet_with_applicability ( cx, pat_span, "<binding_repl>" , app) ;
132
+ let binding_replacement = snippet_with_applicability ( cx, pat_span, "<binding_repl>" , & mut app) ;
147
133
diag. multipart_suggestion_verbose (
148
134
"try" ,
149
135
vec ! [
@@ -154,10 +140,20 @@ fn emit_redundant_guards(
154
140
} ,
155
141
(
156
142
guard_span. source_callsite( ) . with_lo( outer_arm. pat. span. hi( ) ) ,
157
- get_guard( cx, inner_guard, app) ,
143
+ inner_guard. map_or_else( String :: new, |guard| {
144
+ let ( prefix, span) = match guard {
145
+ Guard :: If ( e) => ( "if" , e. span) ,
146
+ Guard :: IfLet ( l) => ( "if let" , l. span) ,
147
+ } ;
148
+
149
+ format!(
150
+ " {prefix} {}" ,
151
+ snippet_with_applicability( cx, span, "<guard>" , & mut app) ,
152
+ )
153
+ } ) ,
158
154
) ,
159
155
] ,
160
- * app,
156
+ app,
161
157
) ;
162
158
} ,
163
159
) ;
0 commit comments