mirror of
https://github.com/rust-lang/rust-clippy
synced 2025-02-17 22:48:48 +00:00
Optimize redundant_clone
by using a static data structure to track transitive relations.
This commit is contained in:
parent
57b3c4b90f
commit
6daa6d5ffe
1 changed files with 36 additions and 25 deletions
|
@ -3,7 +3,7 @@ use clippy_utils::source::snippet_opt;
|
|||
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};
|
||||
|
@ -512,7 +512,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeStorageLive {
|
|||
/// For example, `b = &a; c = &a;` will make `b` and (transitively) `c`
|
||||
/// possible borrowers of `a`.
|
||||
struct PossibleBorrowerVisitor<'a, 'tcx> {
|
||||
possible_borrower: TransitiveRelation<mir::Local>,
|
||||
possible_borrower: TransitiveRelation,
|
||||
body: &'a mir::Body<'tcx>,
|
||||
cx: &'a LateContext<'tcx>,
|
||||
possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
|
||||
|
@ -543,18 +543,10 @@ impl<'a, 'tcx> PossibleBorrowerVisitor<'a, 'tcx> {
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -644,7 +636,7 @@ impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'tcx> {
|
|||
/// For exampel, `_1 = &mut _2` generate _1: {_2,...}
|
||||
/// Known Problems: not sure all borrowed are tracked
|
||||
struct PossibleOriginVisitor<'a, 'tcx> {
|
||||
possible_origin: TransitiveRelation<mir::Local>,
|
||||
possible_origin: TransitiveRelation,
|
||||
body: &'a mir::Body<'tcx>,
|
||||
}
|
||||
|
||||
|
@ -663,18 +655,10 @@ impl<'a, 'tcx> PossibleOriginVisitor<'a, 'tcx> {
|
|||
continue;
|
||||
}
|
||||
|
||||
let borrowers = self.possible_origin.reachable_from(&row);
|
||||
let mut borrowers = self.possible_origin.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);
|
||||
}
|
||||
}
|
||||
map
|
||||
|
@ -766,3 +750,30 @@ impl PossibleBorrowerMap<'_, '_> {
|
|||
self.maybe_live.contains(local)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct TransitiveRelation {
|
||||
relations: FxHashMap<mir::Local, Vec<mir::Local>>,
|
||||
}
|
||||
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<mir::Local> {
|
||||
let mut seen = HybridBitSet::new_empty(domain_size);
|
||||
seen.insert(a);
|
||||
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.remove(a);
|
||||
seen
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue