X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=clippy_lints%2Fsrc%2Fredundant_clone.rs;h=954e702a1f8875e49db76c5c80f5a795762c5703;hb=03960ebab26a1b1d2d43540f47aca6670bdc1e54;hp=530b3396abef698fd0c16baee09116f18c35f28b;hpb=464c85c8c1c71feda6e53eb9d8713bfdafaf7d8b;p=rust.git diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 530b3396abe..954e702a1f8 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -3,7 +3,7 @@ use clippy_utils::ty::{has_drop, is_copy, is_type_diagnostic_item, walk_ptrs_ty_depth}; use clippy_utils::{fn_has_unsatisfiable_preds, match_def_path, paths}; use if_chain::if_chain; -use rustc_data_structures::{fx::FxHashMap, transitive_relation::TransitiveRelation}; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{def_id, Body, FnDecl, HirId}; @@ -15,7 +15,7 @@ Mutability, }; use rustc_middle::ty::{self, fold::TypeVisitor, Ty}; -use rustc_mir::dataflow::{Analysis, AnalysisDomain, GenKill, GenKillAnalysis, ResultsCursor}; +use rustc_mir_dataflow::{Analysis, AnalysisDomain, CallReturnPlaces, GenKill, GenKillAnalysis, ResultsCursor}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::{BytePos, Span}; use rustc_span::sym; @@ -62,6 +62,7 @@ macro_rules! unwrap_or_continue { /// /// Path::new("/a/b").join("c").to_path_buf(); /// ``` + #[clippy::version = "1.32.0"] pub REDUNDANT_CLONE, perf, "`clone()` of an owned value that is going to be dropped immediately" @@ -70,7 +71,7 @@ macro_rules! unwrap_or_continue { declare_lint_pass!(RedundantClone => [REDUNDANT_CLONE]); impl<'tcx> LateLintPass<'tcx> for RedundantClone { - #[allow(clippy::too_many_lines)] + #[expect(clippy::too_many_lines)] fn check_fn( &mut self, cx: &LateContext<'tcx>, @@ -123,7 +124,7 @@ 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) - && is_type_diagnostic_item(cx, arg_ty, sym::string_type)); + && is_type_diagnostic_item(cx, arg_ty, sym::String)); let from_deref = !from_borrow && (match_def_path(cx, fn_def_id, &paths::PATH_TO_PATH_BUF) @@ -134,7 +135,7 @@ fn check_fn( } if let ty::Adt(def, _) = arg_ty.kind() { - if match_def_path(cx, def.did, &paths::MEM_MANUALLY_DROP) { + if def.is_manually_drop() { continue; } } @@ -219,7 +220,7 @@ fn check_fn( continue; } else if let Some(loc) = clone_usage.cloned_consume_or_mutate_loc { // cloned value is mutated, and the clone is alive. - if possible_borrower.is_alive_at(ret_local, loc) { + if possible_borrower.local_is_alive_at(ret_local, loc) { continue; } } @@ -499,11 +500,9 @@ fn terminator_effect( fn call_return_effect( &self, - _in_out: &mut impl GenKill, + _trans: &mut impl GenKill, _block: mir::BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - _return_place: mir::Place<'tcx>, + _return_places: CallReturnPlaces<'_, 'tcx>, ) { // Nothing to do when a call returns successfully } @@ -513,7 +512,7 @@ fn call_return_effect( /// For example, `b = &a; c = &a;` will make `b` and (transitively) `c` /// possible borrowers of `a`. struct PossibleBorrowerVisitor<'a, 'tcx> { - possible_borrower: TransitiveRelation, + possible_borrower: TransitiveRelation, body: &'a mir::Body<'tcx>, cx: &'a LateContext<'tcx>, possible_origin: FxHashMap>, @@ -544,18 +543,10 @@ fn into_map( continue; } - let borrowers = self.possible_borrower.reachable_from(&row); + let mut borrowers = self.possible_borrower.reachable_from(row, self.body.local_decls.len()); + borrowers.remove(mir::Local::from_usize(0)); if !borrowers.is_empty() { - let mut bs = HybridBitSet::new_empty(self.body.local_decls.len()); - for &c in borrowers { - if c != mir::Local::from_usize(0) { - bs.insert(c); - } - } - - if !bs.is_empty() { - map.insert(row, bs); - } + map.insert(row, borrowers); } } @@ -645,7 +636,7 @@ fn visit_terminator(&mut self, terminator: &mir::Terminator<'_>, _loc: mir::Loca /// For exampel, `_1 = &mut _2` generate _1: {_2,...} /// Known Problems: not sure all borrowed are tracked struct PossibleOriginVisitor<'a, 'tcx> { - possible_origin: TransitiveRelation, + possible_origin: TransitiveRelation, body: &'a mir::Body<'tcx>, } @@ -664,18 +655,10 @@ fn into_map(self, cx: &LateContext<'tcx>) -> FxHashMap bool { + fn local_is_alive_at(&mut self, local: mir::Local, at: mir::Location) -> bool { self.maybe_live.seek_after_primary_effect(at); self.maybe_live.contains(local) } } + +#[derive(Default)] +struct TransitiveRelation { + relations: FxHashMap>, +} +impl TransitiveRelation { + fn add(&mut self, a: mir::Local, b: mir::Local) { + self.relations.entry(a).or_default().push(b); + } + + fn reachable_from(&self, a: mir::Local, domain_size: usize) -> HybridBitSet { + let mut seen = HybridBitSet::new_empty(domain_size); + let mut stack = vec![a]; + while let Some(u) = stack.pop() { + if let Some(edges) = self.relations.get(&u) { + for &v in edges { + if seen.insert(v) { + stack.push(v); + } + } + } + } + seen + } +}