]> git.proxmox.com Git - rustc.git/blame - src/librustc_mir/borrow_check/diagnostics/find_use.rs
New upstream version 1.44.1+dfsg1
[rustc.git] / src / librustc_mir / borrow_check / diagnostics / find_use.rs
CommitLineData
8faf50e0
XL
1use std::collections::VecDeque;
2use std::rc::Rc;
3
dfeec247
XL
4use crate::borrow_check::{
5 nll::ToRegionVid,
6 region_infer::{Cause, RegionInferenceContext},
7};
9fa01778 8use crate::util::liveness::{self, DefUse};
8faf50e0 9use rustc_data_structures::fx::FxHashSet;
ba9703b0
XL
10use rustc_middle::mir::visit::{MirVisitable, PlaceContext, Visitor};
11use rustc_middle::mir::{Body, Local, Location};
12use rustc_middle::ty::{RegionVid, TyCtxt};
8faf50e0
XL
13
14crate 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
26struct 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 34impl<'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
95struct 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
102enum DefUseResult {
103 Def,
8faf50e0 104 UseLive { local: Local },
8faf50e0
XL
105 UseDrop { local: Local },
106}
107
dc9dc135 108impl<'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}