]> git.lizzy.rs Git - rust.git/blobdiff - clippy_lints/src/redundant_clone.rs
Auto merge of #68717 - petrochenkov:stabexpat, r=varkor
[rust.git] / clippy_lints / src / redundant_clone.rs
index dc1ff86c0bdcf1f2cbb12f57df3126a39e1aab22..d563eb886ae7e6618dc4832ef3a91572c02c0029 100644 (file)
@@ -1,6 +1,6 @@
 use crate::utils::{
-    fn_has_unsatisfiable_preds, has_drop, is_copy, match_def_path, match_type, paths, snippet_opt, span_lint_hir,
-    span_lint_hir_and_then, walk_ptrs_ty_depth,
+    fn_has_unsatisfiable_preds, has_drop, is_copy, is_type_diagnostic_item, match_def_path, match_type, paths,
+    snippet_opt, span_lint_hir, span_lint_hir_and_then, walk_ptrs_ty_depth,
 };
 use if_chain::if_chain;
 use rustc_data_structures::{fx::FxHashMap, transitive_relation::TransitiveRelation};
@@ -80,20 +80,19 @@ fn check_fn(
         let def_id = cx.tcx.hir().body_owner_def_id(body.id());
 
         // Building MIR for `fn`s with unsatisfiable preds results in ICE.
-        if fn_has_unsatisfiable_preds(cx, def_id) {
+        if fn_has_unsatisfiable_preds(cx, def_id.to_def_id()) {
             return;
         }
 
-        let mir = cx.tcx.optimized_mir(def_id);
-        let mir_read_only = mir.unwrap_read_only();
+        let mir = cx.tcx.optimized_mir(def_id.to_def_id());
 
         let maybe_storage_live_result = MaybeStorageLive
-            .into_engine(cx.tcx, mir, def_id)
+            .into_engine(cx.tcx, mir, def_id.to_def_id())
             .iterate_to_fixpoint()
             .into_results_cursor(mir);
         let mut possible_borrower = {
             let mut vis = PossibleBorrowerVisitor::new(cx, mir);
-            vis.visit_body(&mir_read_only);
+            vis.visit_body(&mir);
             vis.into_map(cx, maybe_storage_live_result)
         };
 
@@ -114,7 +113,8 @@ fn check_fn(
 
             let from_borrow = match_def_path(cx, fn_def_id, &paths::CLONE_TRAIT_METHOD)
                 || match_def_path(cx, fn_def_id, &paths::TO_OWNED_METHOD)
-                || (match_def_path(cx, fn_def_id, &paths::TO_STRING_METHOD) && match_type(cx, arg_ty, &paths::STRING));
+                || (match_def_path(cx, fn_def_id, &paths::TO_STRING_METHOD)
+                    && is_type_diagnostic_item(cx, arg_ty, sym!(string_type)));
 
             let from_deref = !from_borrow
                 && (match_def_path(cx, fn_def_id, &paths::PATH_TO_PATH_BUF)
@@ -146,7 +146,7 @@ fn check_fn(
                 // `arg` is a reference as it is `.deref()`ed in the previous block.
                 // Look into the predecessor block and find out the source of deref.
 
-                let ps = mir_read_only.predecessors_for(bb);
+                let ps = &mir.predecessors()[bb];
                 if ps.len() != 1 {
                     continue;
                 }
@@ -191,7 +191,7 @@ fn check_fn(
                 (local, deref_clone_ret)
             };
 
-            let is_temp = mir_read_only.local_kind(ret_local) == mir::LocalKind::Temp;
+            let is_temp = mir.local_kind(ret_local) == mir::LocalKind::Temp;
 
             // 1. `local` can be moved out if it is not used later.
             // 2. If `ret_local` is a temporary and is neither consumed nor mutated, we can remove this `clone`
@@ -243,20 +243,20 @@ fn check_fn(
                             }
                         }
 
-                        span_lint_hir_and_then(cx, REDUNDANT_CLONE, node, sugg_span, "redundant clone", |db| {
-                            db.span_suggestion(
+                        span_lint_hir_and_then(cx, REDUNDANT_CLONE, node, sugg_span, "redundant clone", |diag| {
+                            diag.span_suggestion(
                                 sugg_span,
                                 "remove this",
                                 String::new(),
                                 app,
                             );
                             if used {
-                                db.span_note(
+                                diag.span_note(
                                     span,
                                     "cloned value is neither consumed nor mutated",
                                 );
                             } else {
-                                db.span_note(
+                                diag.span_note(
                                     span.with_hi(span.lo() + BytePos(u32::try_from(dot).unwrap())),
                                     "this value is dropped without further use",
                                 );
@@ -341,6 +341,9 @@ fn base_local_and_movability<'tcx>(
     let mut deref = false;
     // Accessing a field of an ADT that has `Drop`. Moving the field out will cause E0509.
     let mut field = false;
+    // If projection is a slice index then clone can be removed only if the
+    // underlying type implements Copy
+    let mut slice = false;
 
     let PlaceRef { local, mut projection } = place.as_ref();
     while let [base @ .., elem] = projection {
@@ -348,9 +351,11 @@ fn base_local_and_movability<'tcx>(
         deref |= matches!(elem, mir::ProjectionElem::Deref);
         field |= matches!(elem, mir::ProjectionElem::Field(..))
             && has_drop(cx, mir::Place::ty_from(local, projection, &mir.local_decls, cx.tcx).ty);
+        slice |= matches!(elem, mir::ProjectionElem::Index(..))
+            && !is_copy(cx, mir::Place::ty_from(local, projection, &mir.local_decls, cx.tcx).ty);
     }
 
-    Some((local, deref || field))
+    Some((local, deref || field || slice))
 }
 
 struct LocalUseVisitor {
@@ -586,7 +591,7 @@ struct PossibleBorrowerMap<'a, 'tcx> {
 impl PossibleBorrowerMap<'_, '_> {
     /// Returns true if the set of borrowers of `borrowed` living at `at` matches with `borrowers`.
     fn only_borrowers(&mut self, borrowers: &[mir::Local], borrowed: mir::Local, at: mir::Location) -> bool {
-        self.maybe_live.seek_after(at);
+        self.maybe_live.seek_after_primary_effect(at);
 
         self.bitset.0.clear();
         let maybe_live = &mut self.maybe_live;