clippy_utils/mir/
possible_origin.rs1use super::transitive_relation::TransitiveRelation;
2use crate::ty::is_copy;
3use rustc_data_structures::fx::FxHashMap;
4use rustc_index::bit_set::DenseBitSet;
5use rustc_lint::LateContext;
6use rustc_middle::mir;
7
8pub(super) struct PossibleOriginVisitor<'a, 'tcx> {
12 possible_origin: TransitiveRelation,
13 body: &'a mir::Body<'tcx>,
14}
15
16impl<'a, 'tcx> PossibleOriginVisitor<'a, 'tcx> {
17 pub fn new(body: &'a mir::Body<'tcx>) -> Self {
18 Self {
19 possible_origin: TransitiveRelation::default(),
20 body,
21 }
22 }
23
24 pub fn into_map(self, cx: &LateContext<'tcx>) -> FxHashMap<mir::Local, DenseBitSet<mir::Local>> {
26 let mut map = FxHashMap::default();
27 for row in (1..self.body.local_decls.len()).map(mir::Local::from_usize) {
28 if is_copy(cx, self.body.local_decls[row].ty) {
29 continue;
30 }
31
32 let mut origins = self.possible_origin.reachable_from(row, self.body.local_decls.len());
33 origins.remove(mir::Local::from_usize(0));
34 if !origins.is_empty() {
35 map.insert(row, origins);
36 }
37 }
38 map
39 }
40}
41
42impl<'tcx> mir::visit::Visitor<'tcx> for PossibleOriginVisitor<'_, 'tcx> {
43 fn visit_assign(&mut self, place: &mir::Place<'tcx>, rvalue: &mir::Rvalue<'_>, _location: mir::Location) {
44 let lhs = place.local;
45 match rvalue {
46 mir::Rvalue::Ref(_, mir::BorrowKind::Mut { .. }, borrowed) |
48 mir::Rvalue::Use(mir::Operand::Move(borrowed), _) |
51 mir::Rvalue::Cast(_, mir::Operand::Move(borrowed), _)
53 => {
54 self.possible_origin.add(lhs, borrowed.local);
55 },
56 _ => {},
57 }
58 }
59}