1 use std::collections::VecDeque;
5 def_use::{self, DefUse},
7 region_infer::{Cause, RegionInferenceContext},
9 use rustc_data_structures::fx::FxHashSet;
10 use rustc_middle::mir::visit::{MirVisitable, PlaceContext, Visitor};
11 use rustc_middle::mir::{Body, Local, Location};
12 use rustc_middle::ty::{RegionVid, TyCtxt};
16 regioncx: &Rc<RegionInferenceContext<'tcx>>,
18 region_vid: RegionVid,
19 start_point: Location,
21 let mut uf = UseFinder { body, regioncx, tcx, region_vid, start_point };
26 struct UseFinder<'cx, 'tcx> {
27 body: &'cx Body<'tcx>,
28 regioncx: &'cx Rc<RegionInferenceContext<'tcx>>,
30 region_vid: RegionVid,
31 start_point: Location,
34 impl<'cx, 'tcx> UseFinder<'cx, 'tcx> {
35 fn find(&mut self) -> Option<Cause> {
36 let mut queue = VecDeque::new();
37 let mut visited = FxHashSet::default();
39 queue.push_back(self.start_point);
40 while let Some(p) = queue.pop_front() {
41 if !self.regioncx.region_contains(self.region_vid, p) {
45 if !visited.insert(p) {
49 let block_data = &self.body[p.block];
51 match self.def_use(p, block_data.visitable(p.statement_index)) {
52 Some(DefUseResult::Def) => {}
54 Some(DefUseResult::UseLive { local }) => {
55 return Some(Cause::LiveVar(local, p));
58 Some(DefUseResult::UseDrop { local }) => {
59 return Some(Cause::DropVar(local, p));
63 if p.statement_index < block_data.statements.len() {
64 queue.push_back(p.successor_within_block());
70 .filter(|&bb| Some(&Some(*bb)) != block_data.terminator().unwind())
71 .map(|&bb| Location { statement_index: 0, block: bb }),
81 fn def_use(&self, location: Location, thing: &dyn MirVisitable<'tcx>) -> Option<DefUseResult> {
82 let mut visitor = DefUseVisitor {
85 region_vid: self.region_vid,
89 thing.apply(location, &mut visitor);
91 visitor.def_use_result
95 struct DefUseVisitor<'cx, 'tcx> {
96 body: &'cx Body<'tcx>,
98 region_vid: RegionVid,
99 def_use_result: Option<DefUseResult>,
104 UseLive { local: Local },
105 UseDrop { local: Local },
108 impl<'cx, 'tcx> Visitor<'tcx> for DefUseVisitor<'cx, 'tcx> {
109 fn visit_local(&mut self, &local: &Local, context: PlaceContext, _: Location) {
110 let local_ty = self.body.local_decls[local].ty;
112 let mut found_it = false;
113 self.tcx.for_each_free_region(&local_ty, |r| {
114 if r.to_region_vid() == self.region_vid {
120 self.def_use_result = match def_use::categorize(context) {
121 Some(DefUse::Def) => Some(DefUseResult::Def),
122 Some(DefUse::Use) => Some(DefUseResult::UseLive { local }),
123 Some(DefUse::Drop) => Some(DefUseResult::UseDrop { local }),