]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_borrowck/src/diagnostics/find_use.rs
New upstream version 1.67.1+dfsg1
[rustc.git] / compiler / rustc_borrowck / src / diagnostics / find_use.rs
CommitLineData
487cf647
FG
1#![deny(rustc::untranslatable_diagnostic)]
2#![deny(rustc::diagnostic_outside_of_impl)]
3
8faf50e0
XL
4use std::collections::VecDeque;
5use std::rc::Rc;
6
c295e0f8 7use crate::{
f9f354fc 8 def_use::{self, DefUse},
dfeec247
XL
9 nll::ToRegionVid,
10 region_infer::{Cause, RegionInferenceContext},
11};
8faf50e0 12use rustc_data_structures::fx::FxHashSet;
ba9703b0
XL
13use rustc_middle::mir::visit::{MirVisitable, PlaceContext, Visitor};
14use rustc_middle::mir::{Body, Local, Location};
15use rustc_middle::ty::{RegionVid, TyCtxt};
8faf50e0 16
923072b8 17pub(crate) fn find<'tcx>(
dc9dc135 18 body: &Body<'tcx>,
8faf50e0 19 regioncx: &Rc<RegionInferenceContext<'tcx>>,
dc9dc135 20 tcx: TyCtxt<'tcx>,
8faf50e0
XL
21 region_vid: RegionVid,
22 start_point: Location,
23) -> Option<Cause> {
dfeec247 24 let mut uf = UseFinder { body, regioncx, tcx, region_vid, start_point };
8faf50e0
XL
25
26 uf.find()
27}
28
dc9dc135
XL
29struct UseFinder<'cx, 'tcx> {
30 body: &'cx Body<'tcx>,
8faf50e0 31 regioncx: &'cx Rc<RegionInferenceContext<'tcx>>,
dc9dc135 32 tcx: TyCtxt<'tcx>,
8faf50e0
XL
33 region_vid: RegionVid,
34 start_point: Location,
8faf50e0
XL
35}
36
dc9dc135 37impl<'cx, 'tcx> UseFinder<'cx, 'tcx> {
8faf50e0
XL
38 fn find(&mut self) -> Option<Cause> {
39 let mut queue = VecDeque::new();
0bf4aa26 40 let mut visited = FxHashSet::default();
8faf50e0
XL
41
42 queue.push_back(self.start_point);
43 while let Some(p) = queue.pop_front() {
44 if !self.regioncx.region_contains(self.region_vid, p) {
45 continue;
46 }
47
48 if !visited.insert(p) {
49 continue;
50 }
51
dc9dc135 52 let block_data = &self.body[p.block];
8faf50e0
XL
53
54 match self.def_use(p, block_data.visitable(p.statement_index)) {
55 Some(DefUseResult::Def) => {}
56
57 Some(DefUseResult::UseLive { local }) => {
58 return Some(Cause::LiveVar(local, p));
59 }
60
61 Some(DefUseResult::UseDrop { local }) => {
62 return Some(Cause::DropVar(local, p));
63 }
64
65 None => {
66 if p.statement_index < block_data.statements.len() {
9fa01778 67 queue.push_back(p.successor_within_block());
8faf50e0
XL
68 } else {
69 queue.extend(
70 block_data
71 .terminator()
72 .successors()
923072b8
FG
73 .filter(|&bb| Some(&Some(bb)) != block_data.terminator().unwind())
74 .map(|bb| Location { statement_index: 0, block: bb }),
8faf50e0
XL
75 );
76 }
77 }
78 }
79 }
80
81 None
82 }
83
84 fn def_use(&self, location: Location, thing: &dyn MirVisitable<'tcx>) -> Option<DefUseResult> {
85 let mut visitor = DefUseVisitor {
dc9dc135 86 body: self.body,
8faf50e0
XL
87 tcx: self.tcx,
88 region_vid: self.region_vid,
8faf50e0
XL
89 def_use_result: None,
90 };
91
92 thing.apply(location, &mut visitor);
93
94 visitor.def_use_result
95 }
96}
97
dc9dc135
XL
98struct DefUseVisitor<'cx, 'tcx> {
99 body: &'cx Body<'tcx>,
100 tcx: TyCtxt<'tcx>,
8faf50e0 101 region_vid: RegionVid,
8faf50e0
XL
102 def_use_result: Option<DefUseResult>,
103}
104
105enum DefUseResult {
106 Def,
8faf50e0 107 UseLive { local: Local },
8faf50e0
XL
108 UseDrop { local: Local },
109}
110
dc9dc135 111impl<'cx, 'tcx> Visitor<'tcx> for DefUseVisitor<'cx, 'tcx> {
064997fb 112 fn visit_local(&mut self, local: Local, context: PlaceContext, _: Location) {
dc9dc135 113 let local_ty = self.body.local_decls[local].ty;
8faf50e0
XL
114
115 let mut found_it = false;
116 self.tcx.for_each_free_region(&local_ty, |r| {
117 if r.to_region_vid() == self.region_vid {
118 found_it = true;
119 }
120 });
121
122 if found_it {
f9f354fc 123 self.def_use_result = match def_use::categorize(context) {
b7449926
XL
124 Some(DefUse::Def) => Some(DefUseResult::Def),
125 Some(DefUse::Use) => Some(DefUseResult::UseLive { local }),
126 Some(DefUse::Drop) => Some(DefUseResult::UseDrop { local }),
127 None => None,
128 };
8faf50e0
XL
129 }
130 }
131}