]>
Commit | Line | Data |
---|---|---|
8faf50e0 XL |
1 | use std::collections::VecDeque; |
2 | use std::rc::Rc; | |
3 | ||
dfeec247 XL |
4 | use crate::borrow_check::{ |
5 | nll::ToRegionVid, | |
6 | region_infer::{Cause, RegionInferenceContext}, | |
7 | }; | |
9fa01778 | 8 | use crate::util::liveness::{self, DefUse}; |
8faf50e0 | 9 | use rustc_data_structures::fx::FxHashSet; |
ba9703b0 XL |
10 | use rustc_middle::mir::visit::{MirVisitable, PlaceContext, Visitor}; |
11 | use rustc_middle::mir::{Body, Local, Location}; | |
12 | use rustc_middle::ty::{RegionVid, TyCtxt}; | |
8faf50e0 XL |
13 | |
14 | crate fn find<'tcx>( | |
dc9dc135 | 15 | body: &Body<'tcx>, |
8faf50e0 | 16 | regioncx: &Rc<RegionInferenceContext<'tcx>>, |
dc9dc135 | 17 | tcx: TyCtxt<'tcx>, |
8faf50e0 XL |
18 | region_vid: RegionVid, |
19 | start_point: Location, | |
20 | ) -> Option<Cause> { | |
dfeec247 | 21 | let mut uf = UseFinder { body, regioncx, tcx, region_vid, start_point }; |
8faf50e0 XL |
22 | |
23 | uf.find() | |
24 | } | |
25 | ||
dc9dc135 XL |
26 | struct UseFinder<'cx, 'tcx> { |
27 | body: &'cx Body<'tcx>, | |
8faf50e0 | 28 | regioncx: &'cx Rc<RegionInferenceContext<'tcx>>, |
dc9dc135 | 29 | tcx: TyCtxt<'tcx>, |
8faf50e0 XL |
30 | region_vid: RegionVid, |
31 | start_point: Location, | |
8faf50e0 XL |
32 | } |
33 | ||
dc9dc135 | 34 | impl<'cx, 'tcx> UseFinder<'cx, 'tcx> { |
8faf50e0 XL |
35 | fn find(&mut self) -> Option<Cause> { |
36 | let mut queue = VecDeque::new(); | |
0bf4aa26 | 37 | let mut visited = FxHashSet::default(); |
8faf50e0 XL |
38 | |
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) { | |
42 | continue; | |
43 | } | |
44 | ||
45 | if !visited.insert(p) { | |
46 | continue; | |
47 | } | |
48 | ||
dc9dc135 | 49 | let block_data = &self.body[p.block]; |
8faf50e0 XL |
50 | |
51 | match self.def_use(p, block_data.visitable(p.statement_index)) { | |
52 | Some(DefUseResult::Def) => {} | |
53 | ||
54 | Some(DefUseResult::UseLive { local }) => { | |
55 | return Some(Cause::LiveVar(local, p)); | |
56 | } | |
57 | ||
58 | Some(DefUseResult::UseDrop { local }) => { | |
59 | return Some(Cause::DropVar(local, p)); | |
60 | } | |
61 | ||
62 | None => { | |
63 | if p.statement_index < block_data.statements.len() { | |
9fa01778 | 64 | queue.push_back(p.successor_within_block()); |
8faf50e0 XL |
65 | } else { |
66 | queue.extend( | |
67 | block_data | |
68 | .terminator() | |
69 | .successors() | |
70 | .filter(|&bb| Some(&Some(*bb)) != block_data.terminator().unwind()) | |
dfeec247 | 71 | .map(|&bb| Location { statement_index: 0, block: bb }), |
8faf50e0 XL |
72 | ); |
73 | } | |
74 | } | |
75 | } | |
76 | } | |
77 | ||
78 | None | |
79 | } | |
80 | ||
81 | fn def_use(&self, location: Location, thing: &dyn MirVisitable<'tcx>) -> Option<DefUseResult> { | |
82 | let mut visitor = DefUseVisitor { | |
dc9dc135 | 83 | body: self.body, |
8faf50e0 XL |
84 | tcx: self.tcx, |
85 | region_vid: self.region_vid, | |
8faf50e0 XL |
86 | def_use_result: None, |
87 | }; | |
88 | ||
89 | thing.apply(location, &mut visitor); | |
90 | ||
91 | visitor.def_use_result | |
92 | } | |
93 | } | |
94 | ||
dc9dc135 XL |
95 | struct DefUseVisitor<'cx, 'tcx> { |
96 | body: &'cx Body<'tcx>, | |
97 | tcx: TyCtxt<'tcx>, | |
8faf50e0 | 98 | region_vid: RegionVid, |
8faf50e0 XL |
99 | def_use_result: Option<DefUseResult>, |
100 | } | |
101 | ||
102 | enum DefUseResult { | |
103 | Def, | |
8faf50e0 | 104 | UseLive { local: Local }, |
8faf50e0 XL |
105 | UseDrop { local: Local }, |
106 | } | |
107 | ||
dc9dc135 | 108 | impl<'cx, 'tcx> Visitor<'tcx> for DefUseVisitor<'cx, 'tcx> { |
48663c56 | 109 | fn visit_local(&mut self, &local: &Local, context: PlaceContext, _: Location) { |
dc9dc135 | 110 | let local_ty = self.body.local_decls[local].ty; |
8faf50e0 XL |
111 | |
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 { | |
115 | found_it = true; | |
116 | } | |
117 | }); | |
118 | ||
119 | if found_it { | |
b7449926 XL |
120 | self.def_use_result = match liveness::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 }), | |
124 | None => None, | |
125 | }; | |
8faf50e0 XL |
126 | } |
127 | } | |
128 | } |