@@ -47,12 +47,9 @@ pub(super) fn check(cx: &LateContext<'_>, arms: &[Arm<'_>]) {
4747 arm. guard ,
4848 & mut app,
4949 ) ;
50-
51- continue ;
5250 }
53-
5451 // `Some(x) if let Some(2) = x`
55- if let Guard :: IfLet ( let_expr) = guard
52+ else if let Guard :: IfLet ( let_expr) = guard
5653 && let pat = let_expr. pat
5754 && let Some ( ( pat_binding, field_name) ) = get_pat_binding ( cx, let_expr. init , outer_arm)
5855 {
@@ -66,16 +63,20 @@ pub(super) fn check(cx: &LateContext<'_>, arms: &[Arm<'_>]) {
6663 None ,
6764 & mut app,
6865 ) ;
69-
70- continue ;
7166 }
72-
7367 // `Some(x) if x == Some(2)`
74- if let Guard :: If ( if_expr) = guard
68+ else if let Guard :: If ( if_expr) = guard
7569 && let ExprKind :: Binary ( bin_op, local, pat) = if_expr. kind
7670 && matches ! ( bin_op. node, BinOpKind :: Eq )
7771 && let Some ( ( pat_binding, field_name) ) = get_pat_binding ( cx, local, outer_arm)
7872 && 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)
7980 {
8081 emit_redundant_guard (
8182 cx,
@@ -87,8 +88,6 @@ pub(super) fn check(cx: &LateContext<'_>, arms: &[Arm<'_>]) {
8788 None ,
8889 & mut app,
8990 ) ;
90-
91- continue ;
9291 }
9392 }
9493}
@@ -198,52 +197,30 @@ fn emit_redundant_guard(
198197
199198/// Checks if the given `Expr` can also be represented as a `Pat`.
200199fn 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+ }
247222
248- helper ( cx, expr)
223+ ControlFlow :: Break ( ( ) )
224+ } )
225+ . is_none ( )
249226}
0 commit comments