]> git.lizzy.rs Git - rust.git/commitdiff
Fix FP in `same_item_push`
authorTakayuki Nakata <f.seasons017@gmail.com>
Tue, 1 Sep 2020 13:39:09 +0000 (22:39 +0900)
committerTakayuki Nakata <f.seasons017@gmail.com>
Tue, 1 Sep 2020 13:39:09 +0000 (22:39 +0900)
Don't emit a lint when the pushed item doesn't have Clone trait

clippy_lints/src/loops.rs
tests/ui/same_item_push.rs

index c95e43a9430446b2470aac5c782c10418b23ac57..25345f8fa316c1b87eb016b7fa6c6b9faee0c3a6 100644 (file)
@@ -1140,43 +1140,51 @@ fn detect_same_item_push<'tcx>(
     walk_expr(&mut same_item_push_visitor, body);
     if same_item_push_visitor.should_lint {
         if let Some((vec, pushed_item)) = same_item_push_visitor.vec_push {
-            // Make sure that the push does not involve possibly mutating values
-            if let PatKind::Wild = pat.kind {
-                let vec_str = snippet_with_macro_callsite(cx, vec.span, "");
-                let item_str = snippet_with_macro_callsite(cx, pushed_item.span, "");
-                if let ExprKind::Path(ref qpath) = pushed_item.kind {
-                    if_chain! {
-                        if let Res::Local(hir_id) = qpath_res(cx, qpath, pushed_item.hir_id);
-                        let node = cx.tcx.hir().get(hir_id);
-                        if let Node::Binding(pat) = node;
-                        if let PatKind::Binding(bind_ann, ..) = pat.kind;
-                        if !matches!(bind_ann, BindingAnnotation::RefMut | BindingAnnotation::Mutable);
-                        then {
-                            span_lint_and_help(
-                                cx,
-                                SAME_ITEM_PUSH,
-                                vec.span,
-                                "it looks like the same item is being pushed into this Vec",
-                                None,
-                                &format!(
-                                    "try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})",
-                                    item_str, vec_str, item_str
-                                ),
-                            )
+            let ty = cx.typeck_results().expr_ty(pushed_item);
+            if cx
+                .tcx
+                .lang_items()
+                .clone_trait()
+                .map_or(false, |id| implements_trait(cx, ty, id, &[]))
+            {
+                // Make sure that the push does not involve possibly mutating values
+                if let PatKind::Wild = pat.kind {
+                    let vec_str = snippet_with_macro_callsite(cx, vec.span, "");
+                    let item_str = snippet_with_macro_callsite(cx, pushed_item.span, "");
+                    if let ExprKind::Path(ref qpath) = pushed_item.kind {
+                        if_chain! {
+                            if let Res::Local(hir_id) = qpath_res(cx, qpath, pushed_item.hir_id);
+                            let node = cx.tcx.hir().get(hir_id);
+                            if let Node::Binding(pat) = node;
+                            if let PatKind::Binding(bind_ann, ..) = pat.kind;
+                            if !matches!(bind_ann, BindingAnnotation::RefMut | BindingAnnotation::Mutable);
+                            then {
+                                span_lint_and_help(
+                                    cx,
+                                    SAME_ITEM_PUSH,
+                                    vec.span,
+                                    "it looks like the same item is being pushed into this Vec",
+                                    None,
+                                    &format!(
+                                        "try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})",
+                                        item_str, vec_str, item_str
+                                    ),
+                                )
+                            }
                         }
+                    } else if mutated_variables(pushed_item, cx).map_or(false, |mutvars| mutvars.is_empty()) {
+                        span_lint_and_help(
+                            cx,
+                            SAME_ITEM_PUSH,
+                            vec.span,
+                            "it looks like the same item is being pushed into this Vec",
+                            None,
+                            &format!(
+                                "try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})",
+                                item_str, vec_str, item_str
+                            ),
+                        )
                     }
-                } else if mutated_variables(pushed_item, cx).map_or(false, |mutvars| mutvars.is_empty()) {
-                    span_lint_and_help(
-                        cx,
-                        SAME_ITEM_PUSH,
-                        vec.span,
-                        "it looks like the same item is being pushed into this Vec",
-                        None,
-                        &format!(
-                            "try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})",
-                            item_str, vec_str, item_str
-                        ),
-                    )
                 }
             }
         }
index bfe27e020445c77b83c4ddfb14f773eb4ee36b85..0903a8738265195812bc110d39e376a7472d2651 100644 (file)
@@ -94,4 +94,10 @@ struct A {
         vec13.push(item);
         item += 10;
     }
+
+    // Fix #5979
+    let mut vec14: Vec<std::fs::File> = Vec::new();
+    for _ in 0..10 {
+        vec14.push(std::fs::File::open("foobar").unwrap());
+    }
 }