1 use std::collections::VecDeque;
4 use crate::borrow_check::nll::region_infer::{Cause, RegionInferenceContext};
5 use crate::borrow_check::nll::ToRegionVid;
6 use crate::util::liveness::{self, DefUse};
7 use rustc::mir::visit::{MirVisitable, PlaceContext, Visitor};
8 use rustc::mir::{Local, Location, Body};
9 use rustc::ty::{RegionVid, TyCtxt};
10 use rustc_data_structures::fx::FxHashSet;
14 regioncx: &Rc<RegionInferenceContext<'tcx>>,
15 tcx: TyCtxt<'_, '_, 'tcx>,
16 region_vid: RegionVid,
17 start_point: Location,
19 let mut uf = UseFinder {
30 struct UseFinder<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
32 regioncx: &'cx Rc<RegionInferenceContext<'tcx>>,
33 tcx: TyCtxt<'cx, 'gcx, 'tcx>,
34 region_vid: RegionVid,
35 start_point: Location,
38 impl<'cx, 'gcx, 'tcx> UseFinder<'cx, 'gcx, 'tcx> {
39 fn find(&mut self) -> Option<Cause> {
40 let mut queue = VecDeque::new();
41 let mut visited = FxHashSet::default();
43 queue.push_back(self.start_point);
44 while let Some(p) = queue.pop_front() {
45 if !self.regioncx.region_contains(self.region_vid, p) {
49 if !visited.insert(p) {
53 let block_data = &self.mir[p.block];
55 match self.def_use(p, block_data.visitable(p.statement_index)) {
56 Some(DefUseResult::Def) => {}
58 Some(DefUseResult::UseLive { local }) => {
59 return Some(Cause::LiveVar(local, p));
62 Some(DefUseResult::UseDrop { local }) => {
63 return Some(Cause::DropVar(local, p));
67 if p.statement_index < block_data.statements.len() {
68 queue.push_back(p.successor_within_block());
74 .filter(|&bb| Some(&Some(*bb)) != block_data.terminator().unwind())
88 fn def_use(&self, location: Location, thing: &dyn MirVisitable<'tcx>) -> Option<DefUseResult> {
89 let mut visitor = DefUseVisitor {
92 region_vid: self.region_vid,
96 thing.apply(location, &mut visitor);
98 visitor.def_use_result
102 struct DefUseVisitor<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
103 mir: &'cx Body<'tcx>,
104 tcx: TyCtxt<'cx, 'gcx, 'tcx>,
105 region_vid: RegionVid,
106 def_use_result: Option<DefUseResult>,
111 UseLive { local: Local },
112 UseDrop { local: Local },
115 impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for DefUseVisitor<'cx, 'gcx, 'tcx> {
116 fn visit_local(&mut self, &local: &Local, context: PlaceContext, _: Location) {
117 let local_ty = self.mir.local_decls[local].ty;
119 let mut found_it = false;
120 self.tcx.for_each_free_region(&local_ty, |r| {
121 if r.to_region_vid() == self.region_vid {
127 self.def_use_result = match liveness::categorize(context) {
128 Some(DefUse::Def) => Some(DefUseResult::Def),
129 Some(DefUse::Use) => Some(DefUseResult::UseLive { local }),
130 Some(DefUse::Drop) => Some(DefUseResult::UseDrop { local }),