@@ -47,12 +47,9 @@ pub(super) fn check(cx: &LateContext<'_>, arms: &[Arm<'_>]) {
47
47
arm. guard ,
48
48
& mut app,
49
49
) ;
50
-
51
- continue ;
52
50
}
53
-
54
51
// `Some(x) if let Some(2) = x`
55
- if let Guard :: IfLet ( let_expr) = guard
52
+ else if let Guard :: IfLet ( let_expr) = guard
56
53
&& let pat = let_expr. pat
57
54
&& let Some ( ( pat_binding, field_name) ) = get_pat_binding ( cx, let_expr. init , outer_arm)
58
55
{
@@ -66,16 +63,20 @@ pub(super) fn check(cx: &LateContext<'_>, arms: &[Arm<'_>]) {
66
63
None ,
67
64
& mut app,
68
65
) ;
69
-
70
- continue ;
71
66
}
72
-
73
67
// `Some(x) if x == Some(2)`
74
- if let Guard :: If ( if_expr) = guard
68
+ else if let Guard :: If ( if_expr) = guard
75
69
&& let ExprKind :: Binary ( bin_op, local, pat) = if_expr. kind
76
70
&& matches ! ( bin_op. node, BinOpKind :: Eq )
77
71
&& let Some ( ( pat_binding, field_name) ) = get_pat_binding ( cx, local, outer_arm)
78
72
&& expr_can_be_pat ( cx, pat)
73
+ // Ensure they have the same type. If they don't, we'd need deref coercion which isn't
74
+ // possible (currently) in a pattern. In some cases, you can use something like
75
+ // `as_deref` or similar but in general, we shouldn't lint this as it'd create an
76
+ // extraordinary amount of FPs.
77
+ //
78
+ // This isn't necessary in the other two checks, as they must be a pattern already.
79
+ && cx. typeck_results ( ) . expr_ty ( local) == cx. typeck_results ( ) . expr_ty ( pat)
79
80
{
80
81
emit_redundant_guard (
81
82
cx,
@@ -87,8 +88,6 @@ pub(super) fn check(cx: &LateContext<'_>, arms: &[Arm<'_>]) {
87
88
None ,
88
89
& mut app,
89
90
) ;
90
-
91
- continue ;
92
91
}
93
92
}
94
93
}
@@ -198,52 +197,30 @@ fn emit_redundant_guard(
198
197
199
198
/// Checks if the given `Expr` can also be represented as a `Pat`.
200
199
fn expr_can_be_pat ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) -> bool {
201
- fn helper ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) -> bool {
202
- for_each_expr ( expr, |expr| {
203
- let expr = expr. peel_blocks ( ) ;
204
- if match expr. kind {
205
- ExprKind :: ConstBlock ( ..) => cx. tcx . features ( ) . inline_const_pat ,
206
- ExprKind :: Call ( c, ..) if let ExprKind :: Path ( qpath) = c. kind => {
207
- // Allow ctors
208
- matches ! ( cx. qpath_res( & qpath, c. hir_id) , Res :: Def ( DefKind :: Ctor ( ..) , ..) )
209
- } ,
210
- ExprKind :: AddrOf ( .., expr) => helper ( cx, expr) ,
211
- ExprKind :: Array ( exprs) | ExprKind :: Tup ( exprs) => {
212
- for expr in exprs {
213
- if !helper ( cx, expr) {
214
- return ControlFlow :: Break ( ( ) ) ;
215
- }
216
- }
217
-
218
- true
219
- } ,
220
- ExprKind :: Struct ( _, fields, rest) => {
221
- for field in fields {
222
- if !helper ( cx, field. expr ) {
223
- return ControlFlow :: Break ( ( ) ) ;
224
- }
225
- }
226
-
227
- if rest. is_some ( ) {
228
- return ControlFlow :: Break ( ( ) ) ;
229
- }
230
-
231
- true
232
- } ,
233
- ExprKind :: Path ( qpath) => {
234
- // Can't compare a local with another local in a pat
235
- !matches ! ( cx. qpath_res( & qpath, expr. hir_id) , Res :: Local ( ..) )
236
- } ,
237
- ExprKind :: Lit ( ..) => true ,
238
- _ => false ,
239
- } {
240
- return ControlFlow :: Continue ( ( ) ) ;
241
- }
242
-
243
- ControlFlow :: Break ( ( ) )
244
- } )
245
- . is_none ( )
246
- }
200
+ for_each_expr ( expr, |expr| {
201
+ if match expr. kind {
202
+ ExprKind :: ConstBlock ( ..) => cx. tcx . features ( ) . inline_const_pat ,
203
+ ExprKind :: Call ( c, ..) if let ExprKind :: Path ( qpath) = c. kind => {
204
+ // Allow ctors
205
+ matches ! ( cx. qpath_res( & qpath, c. hir_id) , Res :: Def ( DefKind :: Ctor ( ..) , ..) )
206
+ } ,
207
+ ExprKind :: Path ( qpath) => {
208
+ matches ! (
209
+ cx. qpath_res( & qpath, expr. hir_id) ,
210
+ Res :: Def ( DefKind :: Struct | DefKind :: Enum | DefKind :: Ctor ( ..) , ..) ,
211
+ )
212
+ } ,
213
+ ExprKind :: AddrOf ( ..)
214
+ | ExprKind :: Array ( ..)
215
+ | ExprKind :: Tup ( ..)
216
+ | ExprKind :: Struct ( ..)
217
+ | ExprKind :: Lit ( ..) => true ,
218
+ _ => false ,
219
+ } {
220
+ return ControlFlow :: Continue ( ( ) ) ;
221
+ }
247
222
248
- helper ( cx, expr)
223
+ ControlFlow :: Break ( ( ) )
224
+ } )
225
+ . is_none ( )
249
226
}
0 commit comments