rustc_mir_dataflow/impls/
borrowed_locals.rs1use rustc_index::bit_set::DenseBitSet;
2use rustc_middle::mir::*;
3
4use crate::{Analysis, GenKill};
5
6pub struct MaybeBorrowedLocals;
14
15impl MaybeBorrowedLocals {
16 pub(super) fn gen_statement(state: &mut DenseBitSet<Local>, stmt: &Statement<'_>) {
17 if let StatementKind::Assign((_, rvalue)) = &stmt.kind {
18 match rvalue {
19 Rvalue::RawPtr(_, borrowed_place)
22 | Rvalue::Ref(_, BorrowKind::Mut { .. } | BorrowKind::Shared, borrowed_place)
23 | Rvalue::Reborrow(_, _, borrowed_place) => {
24 if !borrowed_place.is_indirect() {
25 state.insert(borrowed_place.local);
26 }
27 }
28
29 Rvalue::Cast(..)
30 | Rvalue::Ref(_, BorrowKind::Fake(_), _)
31 | Rvalue::Use(..)
32 | Rvalue::ThreadLocalRef(..)
33 | Rvalue::Repeat(..)
34 | Rvalue::BinaryOp(..)
35 | Rvalue::UnaryOp(..)
36 | Rvalue::Discriminant(..)
37 | Rvalue::Aggregate(..)
38 | Rvalue::CopyForDeref(..)
39 | Rvalue::WrapUnsafeBinder(..) => {}
40 }
41 }
42 }
43
44 pub(super) fn gen_terminator(state: &mut DenseBitSet<Local>, terminator: &Terminator<'_>) {
45 match terminator.kind {
46 TerminatorKind::Drop { place: dropped_place, .. } => {
47 if !dropped_place.is_indirect() {
56 state.insert(dropped_place.local);
57 }
58 }
59
60 TerminatorKind::UnwindTerminate(_)
61 | TerminatorKind::Assert { .. }
62 | TerminatorKind::Call { .. }
63 | TerminatorKind::FalseEdge { .. }
64 | TerminatorKind::FalseUnwind { .. }
65 | TerminatorKind::CoroutineDrop
66 | TerminatorKind::Goto { .. }
67 | TerminatorKind::InlineAsm { .. }
68 | TerminatorKind::UnwindResume
69 | TerminatorKind::Return
70 | TerminatorKind::TailCall { .. }
71 | TerminatorKind::SwitchInt { .. }
72 | TerminatorKind::Unreachable
73 | TerminatorKind::Yield { .. } => {}
74 }
75 }
76}
77
78impl<'tcx> Analysis<'tcx> for MaybeBorrowedLocals {
79 type Domain = DenseBitSet<Local>;
80 const NAME: &'static str = "maybe_borrowed_locals";
81
82 fn bottom_value(&self, body: &Body<'tcx>) -> Self::Domain {
83 DenseBitSet::new_empty(body.local_decls().len())
85 }
86
87 fn initialize_start_block(&self, _: &Body<'tcx>, _: &mut Self::Domain) {
88 }
90
91 fn apply_primary_statement_effect(
92 &self,
93 state: &mut Self::Domain,
94 statement: &Statement<'tcx>,
95 _location: Location,
96 ) {
97 Self::gen_statement(state, statement);
98
99 if let StatementKind::StorageDead(local) = statement.kind {
102 state.kill(local);
103 }
104 }
105
106 fn apply_primary_terminator_effect(
107 &self,
108 state: &mut Self::Domain,
109 terminator: &Terminator<'tcx>,
110 _location: Location,
111 ) {
112 Self::gen_terminator(state, terminator);
113 }
114}
115
116pub fn borrowed_locals(body: &Body<'_>) -> DenseBitSet<Local> {
118 let mut borrowed = DenseBitSet::new_empty(body.local_decls.len());
119 for bb_data in body.basic_blocks.iter() {
120 for stmt in &bb_data.statements {
121 MaybeBorrowedLocals::gen_statement(&mut borrowed, stmt);
122 }
123 MaybeBorrowedLocals::gen_terminator(&mut borrowed, bb_data.terminator());
124 }
125 borrowed
126}