@@ -14,6 +14,8 @@ use rustc_session::declare_lint_pass;
1414use rustc_span:: source_map:: Spanned ;
1515use rustc_span:: sym;
1616
17+ use std:: ops:: ControlFlow ;
18+
1719declare_clippy_lint ! {
1820 /// ### What it does
1921 /// 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
454456}
455457
456458fn 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?)
464474}
465475
466476fn suggest_cloned_string_to_string ( cx : & LateContext < ' _ > , span : rustc_span:: Span ) {
0 commit comments