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};
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>,
}
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;
}
}
/// 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>>,
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);
}
}
.flat_map(HybridBitSet::iter)
.collect();
- if ContainsRegion
- .visit_ty(self.body.local_decls[*dest].ty)
- .is_break()
- {
+ if ContainsRegion.visit_ty(self.body.local_decls[*dest].ty).is_break() {
mutable_variables.push(*dest);
}
/// 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>,
}
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
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);
+ 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
+ }
+}