@@ -14,6 +14,8 @@ use rustc_session::declare_lint_pass;
14
14
use rustc_span:: source_map:: Spanned ;
15
15
use rustc_span:: sym;
16
16
17
+ use std:: ops:: ControlFlow ;
18
+
17
19
declare_clippy_lint ! {
18
20
/// ### What it does
19
21
/// Checks for string appends of the form `x = x + y` (without
@@ -454,13 +456,21 @@ fn is_parent_map_like(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<rustc_spa
454
456
}
455
457
456
458
fn is_called_from_map_like ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) -> Option < rustc_span:: Span > {
457
- let parent = get_parent_expr ( cx, expr) ?;
458
-
459
- if matches ! ( parent. kind, ExprKind :: Closure ( _) ) {
460
- is_parent_map_like ( cx, parent)
461
- } else {
462
- None
463
- }
459
+ // Look for a closure as parent of `expr`, discarding simple blocks
460
+ let parent_closure = cx
461
+ . tcx
462
+ . hir_parent_iter ( expr. hir_id )
463
+ . try_fold ( expr. hir_id , |child_hir_id, ( _, node) | match node {
464
+ // Check that the child expression is the only expression in the block
465
+ Node :: Block ( block) if block. stmts . is_empty ( ) && block. expr . map ( |e| e. hir_id ) == Some ( child_hir_id) => {
466
+ ControlFlow :: Continue ( block. hir_id )
467
+ } ,
468
+ Node :: Expr ( expr) if matches ! ( expr. kind, ExprKind :: Block ( ..) ) => ControlFlow :: Continue ( expr. hir_id ) ,
469
+ Node :: Expr ( expr) if matches ! ( expr. kind, ExprKind :: Closure ( _) ) => ControlFlow :: Break ( Some ( expr) ) ,
470
+ _ => ControlFlow :: Break ( None ) ,
471
+ } )
472
+ . break_value ( ) ?;
473
+ is_parent_map_like ( cx, parent_closure?)
464
474
}
465
475
466
476
fn suggest_cloned_string_to_string ( cx : & LateContext < ' _ > , span : rustc_span:: Span ) {
0 commit comments