rustc_borrowck/polonius/legacy/
accesses.rs
1use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
2use rustc_middle::mir::{Body, Local, Location, Place};
3use rustc_middle::ty::TyCtxt;
4use rustc_mir_dataflow::move_paths::{LookupResult, MoveData};
5use tracing::debug;
6
7use super::{LocationIndex, PoloniusFacts, PoloniusLocationTable};
8use crate::def_use::{self, DefUse};
9use crate::universal_regions::UniversalRegions;
10
11pub(crate) fn emit_access_facts<'tcx>(
13 tcx: TyCtxt<'tcx>,
14 facts: &mut PoloniusFacts,
15 body: &Body<'tcx>,
16 location_table: &PoloniusLocationTable,
17 move_data: &MoveData<'tcx>,
18 universal_regions: &UniversalRegions<'tcx>,
19) {
20 let mut extractor = AccessFactsExtractor { facts, move_data, location_table };
21 extractor.visit_body(body);
22
23 for (local, local_decl) in body.local_decls.iter_enumerated() {
24 debug!("add use_of_var_derefs_origin facts - local={:?}, type={:?}", local, local_decl.ty);
25 tcx.for_each_free_region(&local_decl.ty, |region| {
26 let region_vid = universal_regions.to_region_vid(region);
27 facts.use_of_var_derefs_origin.push((local, region_vid.into()));
28 });
29 }
30}
31
32struct AccessFactsExtractor<'a, 'tcx> {
34 facts: &'a mut PoloniusFacts,
35 move_data: &'a MoveData<'tcx>,
36 location_table: &'a PoloniusLocationTable,
37}
38
39impl<'tcx> AccessFactsExtractor<'_, 'tcx> {
40 fn location_to_index(&self, location: Location) -> LocationIndex {
41 self.location_table.mid_index(location)
42 }
43}
44
45impl<'a, 'tcx> Visitor<'tcx> for AccessFactsExtractor<'a, 'tcx> {
46 fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) {
47 match def_use::categorize(context) {
48 Some(DefUse::Def) => {
49 debug!("AccessFactsExtractor - emit def");
50 self.facts.var_defined_at.push((local, self.location_to_index(location)));
51 }
52 Some(DefUse::Use) => {
53 debug!("AccessFactsExtractor - emit use");
54 self.facts.var_used_at.push((local, self.location_to_index(location)));
55 }
56 Some(DefUse::Drop) => {
57 debug!("AccessFactsExtractor - emit drop");
58 self.facts.var_dropped_at.push((local, self.location_to_index(location)));
59 }
60 _ => (),
61 }
62 }
63
64 fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
65 self.super_place(place, context, location);
66
67 match context {
68 PlaceContext::NonMutatingUse(_)
69 | PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
70 let path = match self.move_data.rev_lookup.find(place.as_ref()) {
71 LookupResult::Exact(path) | LookupResult::Parent(Some(path)) => path,
72 _ => {
73 return;
75 }
76 };
77 debug!("AccessFactsExtractor - emit path access ({path:?}, {location:?})");
78 self.facts.path_accessed_at_base.push((path, self.location_to_index(location)));
79 }
80
81 _ => {}
82 }
83 }
84}