rustc_borrowck/
used_muts.rs1use rustc_data_structures::fx::FxIndexSet;
2use rustc_middle::mir::visit::{PlaceContext, Visitor};
3use rustc_middle::mir::{
4 Local, Location, Place, Statement, StatementKind, Terminator, TerminatorKind,
5};
6use tracing::debug;
7
8use crate::MirBorrowckCtxt;
9
10impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
11 pub(crate) fn gather_used_muts(
27 &mut self,
28 temporary_used_locals: FxIndexSet<Local>,
29 mut never_initialized_mut_locals: FxIndexSet<Local>,
30 ) {
31 {
32 let mut visitor = GatherUsedMutsVisitor {
33 temporary_used_locals,
34 never_initialized_mut_locals: &mut never_initialized_mut_locals,
35 mbcx: self,
36 };
37 visitor.visit_body(visitor.mbcx.body);
38 }
39
40 debug!("gather_used_muts: never_initialized_mut_locals={:?}", never_initialized_mut_locals);
43 self.used_mut = self.used_mut.union(&never_initialized_mut_locals).cloned().collect();
44 }
45}
46
47struct GatherUsedMutsVisitor<'a, 'b, 'infcx, 'tcx> {
50 temporary_used_locals: FxIndexSet<Local>,
51 never_initialized_mut_locals: &'a mut FxIndexSet<Local>,
52 mbcx: &'a mut MirBorrowckCtxt<'b, 'infcx, 'tcx>,
53}
54
55impl GatherUsedMutsVisitor<'_, '_, '_, '_> {
56 fn remove_never_initialized_mut_locals(&mut self, into: Place<'_>) {
57 self.never_initialized_mut_locals.swap_remove(&into.local);
64 }
65}
66
67impl<'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'_, '_, '_, 'tcx> {
68 fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
69 debug!("visit_terminator: terminator={:?}", terminator);
70 match &terminator.kind {
71 TerminatorKind::Call { destination, .. } => {
72 self.remove_never_initialized_mut_locals(*destination);
73 }
74 _ => {}
75 }
76
77 self.super_terminator(terminator, location);
78 }
79
80 fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
81 if let StatementKind::Assign(box (into, _)) = &statement.kind {
82 debug!(
83 "visit_statement: statement={:?} local={:?} \
84 never_initialized_mut_locals={:?}",
85 statement, into.local, self.never_initialized_mut_locals
86 );
87 self.remove_never_initialized_mut_locals(*into);
88 }
89
90 self.super_statement(statement, location);
91 }
92
93 fn visit_local(&mut self, local: Local, place_context: PlaceContext, location: Location) {
94 if place_context.is_place_assignment() && self.temporary_used_locals.contains(&local) {
95 for moi in &self.mbcx.move_data.loc_map[location] {
97 let mpi = &self.mbcx.move_data.moves[*moi].path;
98 let path = &self.mbcx.move_data.move_paths[*mpi];
99 debug!(
100 "assignment of {:?} to {:?}, adding {:?} to used mutable set",
101 path.place, local, path.place
102 );
103 if let Some(user_local) = path.place.as_local() {
104 self.mbcx.used_mut.insert(user_local);
105 }
106 }
107 }
108 }
109}