11use clippy_utils:: diagnostics:: span_lint_and_then;
22use clippy_utils:: path_to_local;
3- use clippy_utils:: source:: snippet_with_applicability ;
3+ use clippy_utils:: source:: snippet ;
44use clippy_utils:: visitors:: { for_each_expr, is_local_used} ;
55use rustc_ast:: { BorrowKind , LitKind } ;
66use rustc_errors:: Applicability ;
@@ -9,6 +9,7 @@ use rustc_hir::{Arm, BinOpKind, Expr, ExprKind, Guard, MatchSource, Node, Pat, P
99use rustc_lint:: LateContext ;
1010use rustc_span:: symbol:: Ident ;
1111use rustc_span:: Span ;
12+ use std:: borrow:: Cow ;
1213use std:: ops:: ControlFlow ;
1314
1415use super :: REDUNDANT_GUARDS ;
@@ -41,7 +42,14 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>]) {
4142 ( PatKind :: Ref ( ..) , None ) | ( _, Some ( _) ) => continue ,
4243 _ => arm. pat . span ,
4344 } ;
44- emit_redundant_guards ( cx, outer_arm, if_expr. span , pat_span, & binding, arm. guard ) ;
45+ emit_redundant_guards (
46+ cx,
47+ outer_arm,
48+ if_expr. span ,
49+ snippet ( cx, pat_span, "<binding>" ) ,
50+ & binding,
51+ arm. guard ,
52+ ) ;
4553 }
4654 // `Some(x) if let Some(2) = x`
4755 else if let Guard :: IfLet ( let_expr) = guard
@@ -52,7 +60,14 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>]) {
5260 ( PatKind :: Ref ( ..) , None ) | ( _, Some ( _) ) => continue ,
5361 _ => let_expr. pat . span ,
5462 } ;
55- emit_redundant_guards ( cx, outer_arm, let_expr. span , pat_span, & binding, None ) ;
63+ emit_redundant_guards (
64+ cx,
65+ outer_arm,
66+ let_expr. span ,
67+ snippet ( cx, pat_span, "<binding>" ) ,
68+ & binding,
69+ None ,
70+ ) ;
5671 }
5772 // `Some(x) if x == Some(2)`
5873 // `Some(x) if Some(2) == x`
@@ -78,7 +93,25 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>]) {
7893 ( ExprKind :: AddrOf ( ..) , None ) | ( _, Some ( _) ) => continue ,
7994 _ => pat. span ,
8095 } ;
81- emit_redundant_guards ( cx, outer_arm, if_expr. span , pat_span, & binding, None ) ;
96+ emit_redundant_guards (
97+ cx,
98+ outer_arm,
99+ if_expr. span ,
100+ snippet ( cx, pat_span, "<binding>" ) ,
101+ & binding,
102+ None ,
103+ ) ;
104+ } else if let Guard :: If ( if_expr) = guard
105+ && let ExprKind :: MethodCall ( path, recv, ..) = if_expr. kind
106+ && let Some ( binding) = get_pat_binding ( cx, recv, outer_arm)
107+ {
108+ let ty = cx. typeck_results ( ) . expr_ty ( recv) . peel_refs ( ) ;
109+
110+ if path. ident . name == sym ! ( is_empty) && ty. is_str ( ) {
111+ // `s if s.is_empty()` becomes ""
112+
113+ emit_redundant_guards ( cx, outer_arm, if_expr. span , r#""""# . into ( ) , & binding, None )
114+ }
82115 }
83116 }
84117}
@@ -134,19 +167,16 @@ fn emit_redundant_guards<'tcx>(
134167 cx : & LateContext < ' tcx > ,
135168 outer_arm : & Arm < ' tcx > ,
136169 guard_span : Span ,
137- pat_span : Span ,
170+ binding_replacement : Cow < ' static , str > ,
138171 pat_binding : & PatBindingInfo ,
139172 inner_guard : Option < Guard < ' _ > > ,
140173) {
141- let mut app = Applicability :: MaybeIncorrect ;
142-
143174 span_lint_and_then (
144175 cx,
145176 REDUNDANT_GUARDS ,
146177 guard_span. source_callsite ( ) ,
147178 "redundant guard" ,
148179 |diag| {
149- let binding_replacement = snippet_with_applicability ( cx, pat_span, "<binding_repl>" , & mut app) ;
150180 let suggestion_span = match * pat_binding {
151181 PatBindingInfo {
152182 span,
@@ -170,14 +200,11 @@ fn emit_redundant_guards<'tcx>(
170200 Guard :: IfLet ( l) => ( "if let" , l. span) ,
171201 } ;
172202
173- format!(
174- " {prefix} {}" ,
175- snippet_with_applicability( cx, span, "<guard>" , & mut app) ,
176- )
203+ format!( " {prefix} {}" , snippet( cx, span, "<guard>" ) )
177204 } ) ,
178205 ) ,
179206 ] ,
180- app ,
207+ Applicability :: MaybeIncorrect ,
181208 ) ;
182209 } ,
183210 ) ;
0 commit comments