Skip to content

Commit 9347bf4

Browse files
committed
Additional cleanup
This cleans up the refactoring from the previous patch and cleans things up a bit. Each module has a clear entry point and everything else is private.
1 parent f5f98d7 commit 9347bf4

File tree

4 files changed

+151
-130
lines changed

4 files changed

+151
-130
lines changed

compiler/rustc_typeck/src/check/generator_interior/drop_ranges.rs

Lines changed: 9 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -12,39 +12,33 @@
1212
//! The end result is a data structure that maps the post-order index of each node in the HIR tree
1313
//! to a set of values that are known to be dropped at that location.
1414
15-
use self::cfg_build::DropRangeVisitor;
16-
use self::record_consumed_borrow::ExprUseDelegate;
15+
use self::cfg_build::build_control_flow_graph;
16+
use self::record_consumed_borrow::find_consumed_and_borrowed;
1717
use crate::check::FnCtxt;
1818
use hir::def_id::DefId;
19-
use hir::{Body, HirId, HirIdMap, Node, intravisit};
19+
use hir::{Body, HirId, HirIdMap, Node};
2020
use rustc_hir as hir;
2121
use rustc_index::bit_set::BitSet;
2222
use rustc_index::vec::IndexVec;
23-
use rustc_middle::hir::map::Map;
2423
use std::collections::BTreeMap;
2524
use std::fmt::Debug;
26-
use std::mem::swap;
2725

2826
mod cfg_build;
29-
mod record_consumed_borrow;
3027
mod cfg_propagate;
3128
mod cfg_visualize;
29+
mod record_consumed_borrow;
3230

3331
pub fn compute_drop_ranges<'a, 'tcx>(
3432
fcx: &'a FnCtxt<'a, 'tcx>,
3533
def_id: DefId,
3634
body: &'tcx Body<'tcx>,
3735
) -> DropRanges {
38-
let mut expr_use_visitor = ExprUseDelegate::new(fcx.tcx.hir());
39-
expr_use_visitor.consume_body(fcx, def_id, body);
36+
let consumed_borrowed_places = find_consumed_and_borrowed(fcx, def_id, body);
4037

41-
let mut drop_range_visitor = DropRangeVisitor::from_uses(
42-
expr_use_visitor,
43-
fcx.tcx.region_scope_tree(def_id).body_expr_count(body.id()).unwrap_or(0),
44-
);
45-
intravisit::walk_body(&mut drop_range_visitor, body);
38+
let num_exprs = fcx.tcx.region_scope_tree(def_id).body_expr_count(body.id()).unwrap_or(0);
39+
let mut drop_ranges =
40+
build_control_flow_graph(fcx.tcx.hir(), consumed_borrowed_places, body, num_exprs);
4641

47-
let mut drop_ranges = drop_range_visitor.into_drop_ranges();
4842
drop_ranges.propagate_to_fixpoint();
4943

5044
drop_ranges
@@ -105,31 +99,6 @@ impl Debug for DropRanges {
10599
/// (hir_id, post_order_id) -> bool, where a true value indicates that the value is definitely
106100
/// dropped at the point of the node identified by post_order_id.
107101
impl DropRanges {
108-
pub fn new(hir_ids: impl Iterator<Item = HirId>, hir: &Map<'_>, num_exprs: usize) -> Self {
109-
let mut hir_id_map = HirIdMap::<HirIdIndex>::default();
110-
let mut next = <_>::from(0u32);
111-
for hir_id in hir_ids {
112-
for_each_consumable(hir_id, hir.find(hir_id), |hir_id| {
113-
if !hir_id_map.contains_key(&hir_id) {
114-
hir_id_map.insert(hir_id, next);
115-
next = <_>::from(next.index() + 1);
116-
}
117-
});
118-
}
119-
debug!("hir_id_map: {:?}", hir_id_map);
120-
let num_values = hir_id_map.len();
121-
Self {
122-
hir_id_map,
123-
nodes: IndexVec::from_fn_n(|_| NodeInfo::new(num_values), num_exprs + 1),
124-
deferred_edges: <_>::default(),
125-
post_order_map: <_>::default(),
126-
}
127-
}
128-
129-
fn hidx(&self, hir_id: HirId) -> HirIdIndex {
130-
*self.hir_id_map.get(&hir_id).unwrap()
131-
}
132-
133102
pub fn is_dropped_at(&mut self, hir_id: HirId, location: usize) -> bool {
134103
self.hir_id_map
135104
.get(&hir_id)
@@ -142,13 +111,6 @@ impl DropRanges {
142111
self.hir_id_map.len()
143112
}
144113

145-
/// Adds an entry in the mapping from HirIds to PostOrderIds
146-
///
147-
/// Needed so that `add_control_edge_hir_id` can work.
148-
pub fn add_node_mapping(&mut self, hir_id: HirId, post_order_id: usize) {
149-
self.post_order_map.insert(hir_id, post_order_id);
150-
}
151-
152114
/// Returns a reference to the NodeInfo for a node, panicking if it does not exist
153115
fn expect_node(&self, id: PostOrderId) -> &NodeInfo {
154116
&self.nodes[id]
@@ -160,48 +122,10 @@ impl DropRanges {
160122
&mut self.nodes[id]
161123
}
162124

163-
pub fn add_control_edge(&mut self, from: usize, to: usize) {
125+
fn add_control_edge(&mut self, from: usize, to: usize) {
164126
trace!("adding control edge from {} to {}", from, to);
165127
self.node_mut(from.into()).successors.push(to.into());
166128
}
167-
168-
/// Like add_control_edge, but uses a hir_id as the target.
169-
///
170-
/// This can be used for branches where we do not know the PostOrderId of the target yet,
171-
/// such as when handling `break` or `continue`.
172-
pub fn add_control_edge_hir_id(&mut self, from: usize, to: HirId) {
173-
self.deferred_edges.push((from, to));
174-
}
175-
176-
/// Looks up PostOrderId for any control edges added by HirId and adds a proper edge for them.
177-
///
178-
/// Should be called after visiting the HIR but before solving the control flow, otherwise some
179-
/// edges will be missed.
180-
fn process_deferred_edges(&mut self) {
181-
let mut edges = vec![];
182-
swap(&mut edges, &mut self.deferred_edges);
183-
edges.into_iter().for_each(|(from, to)| {
184-
let to = *self.post_order_map.get(&to).expect("Expression ID not found");
185-
trace!("Adding deferred edge from {} to {}", from, to);
186-
self.add_control_edge(from, to)
187-
});
188-
}
189-
190-
pub fn drop_at(&mut self, value: HirId, location: usize) {
191-
let value = self.hidx(value);
192-
self.node_mut(location.into()).drops.push(value);
193-
}
194-
195-
pub fn reinit_at(&mut self, value: HirId, location: usize) {
196-
let value = match self.hir_id_map.get(&value) {
197-
Some(value) => *value,
198-
// If there's no value, this is never consumed and therefore is never dropped. We can
199-
// ignore this.
200-
None => return,
201-
};
202-
self.node_mut(location.into()).reinits.push(value);
203-
}
204-
205129
}
206130

207131
#[derive(Debug)]

compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs

Lines changed: 89 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,57 @@
1-
use super::{for_each_consumable, record_consumed_borrow::ExprUseDelegate, DropRanges};
1+
use super::{
2+
for_each_consumable, record_consumed_borrow::ConsumedAndBorrowedPlaces, DropRanges, HirIdIndex,
3+
NodeInfo,
4+
};
25
use hir::{
36
intravisit::{self, NestedVisitorMap, Visitor},
4-
Expr, ExprKind, Guard, HirId, HirIdMap, HirIdSet,
7+
Body, Expr, ExprKind, Guard, HirId, HirIdMap,
58
};
69
use rustc_hir as hir;
10+
use rustc_index::vec::IndexVec;
711
use rustc_middle::hir::map::Map;
812

13+
/// Traverses the body to find the control flow graph and locations for the
14+
/// relevant places are dropped or reinitialized.
15+
///
16+
/// The resulting structure still needs to be iterated to a fixed point, which
17+
/// can be done with propagate_to_fixpoint in cfg_propagate.
18+
pub fn build_control_flow_graph<'tcx>(
19+
hir: Map<'tcx>,
20+
consumed_borrowed_places: ConsumedAndBorrowedPlaces,
21+
body: &'tcx Body<'tcx>,
22+
num_exprs: usize,
23+
) -> DropRanges {
24+
let mut drop_range_visitor = DropRangeVisitor::new(hir, consumed_borrowed_places, num_exprs);
25+
intravisit::walk_body(&mut drop_range_visitor, body);
26+
drop_range_visitor.drop_ranges
27+
}
28+
929
/// This struct is used to gather the information for `DropRanges` to determine the regions of the
1030
/// HIR tree for which a value is dropped.
1131
///
1232
/// We are interested in points where a variables is dropped or initialized, and the control flow
1333
/// of the code. We identify locations in code by their post-order traversal index, so it is
1434
/// important for this traversal to match that in `RegionResolutionVisitor` and `InteriorVisitor`.
15-
pub struct DropRangeVisitor<'tcx> {
35+
struct DropRangeVisitor<'tcx> {
1636
hir: Map<'tcx>,
17-
/// Maps a HirId to a set of HirIds that are dropped by that node.
18-
///
19-
/// See also the more detailed comment on `ExprUseDelegate.consumed_places`.
20-
consumed_places: HirIdMap<HirIdSet>,
21-
borrowed_places: HirIdSet,
37+
places: ConsumedAndBorrowedPlaces,
2238
drop_ranges: DropRanges,
2339
expr_count: usize,
2440
}
2541

2642
impl<'tcx> DropRangeVisitor<'tcx> {
27-
pub fn from_uses(uses: ExprUseDelegate<'tcx>, num_exprs: usize) -> Self {
28-
debug!("consumed_places: {:?}", uses.consumed_places);
43+
fn new(hir: Map<'tcx>, places: ConsumedAndBorrowedPlaces, num_exprs: usize) -> Self {
44+
debug!("consumed_places: {:?}", places.consumed);
2945
let drop_ranges = DropRanges::new(
30-
uses.consumed_places.iter().flat_map(|(_, places)| places.iter().copied()),
31-
&uses.hir,
46+
places.consumed.iter().flat_map(|(_, places)| places.iter().copied()),
47+
hir,
3248
num_exprs,
3349
);
34-
Self {
35-
hir: uses.hir,
36-
consumed_places: uses.consumed_places,
37-
borrowed_places: uses.borrowed_places,
38-
drop_ranges,
39-
expr_count: 0,
40-
}
41-
}
42-
43-
pub fn into_drop_ranges(self) -> DropRanges {
44-
self.drop_ranges
50+
Self { hir, places, drop_ranges, expr_count: 0 }
4551
}
4652

4753
fn record_drop(&mut self, hir_id: HirId) {
48-
if self.borrowed_places.contains(&hir_id) {
54+
if self.places.borrowed.contains(&hir_id) {
4955
debug!("not marking {:?} as dropped because it is borrowed at some point", hir_id);
5056
} else {
5157
debug!("marking {:?} as dropped at {}", hir_id, self.expr_count);
@@ -59,7 +65,8 @@ impl<'tcx> DropRangeVisitor<'tcx> {
5965
fn consume_expr(&mut self, expr: &hir::Expr<'_>) {
6066
debug!("consuming expr {:?}, count={}", expr.hir_id, self.expr_count);
6167
let places = self
62-
.consumed_places
68+
.places
69+
.consumed
6370
.get(&expr.hir_id)
6471
.map_or(vec![], |places| places.iter().cloned().collect());
6572
for place in places {
@@ -167,3 +174,60 @@ impl<'tcx> Visitor<'tcx> for DropRangeVisitor<'tcx> {
167174
self.expr_count += 1;
168175
}
169176
}
177+
178+
impl DropRanges {
179+
fn new(hir_ids: impl Iterator<Item = HirId>, hir: Map<'_>, num_exprs: usize) -> Self {
180+
let mut hir_id_map = HirIdMap::<HirIdIndex>::default();
181+
let mut next = <_>::from(0u32);
182+
for hir_id in hir_ids {
183+
for_each_consumable(hir_id, hir.find(hir_id), |hir_id| {
184+
if !hir_id_map.contains_key(&hir_id) {
185+
hir_id_map.insert(hir_id, next);
186+
next = <_>::from(next.index() + 1);
187+
}
188+
});
189+
}
190+
debug!("hir_id_map: {:?}", hir_id_map);
191+
let num_values = hir_id_map.len();
192+
Self {
193+
hir_id_map,
194+
nodes: IndexVec::from_fn_n(|_| NodeInfo::new(num_values), num_exprs + 1),
195+
deferred_edges: <_>::default(),
196+
post_order_map: <_>::default(),
197+
}
198+
}
199+
200+
fn hidx(&self, hir_id: HirId) -> HirIdIndex {
201+
*self.hir_id_map.get(&hir_id).unwrap()
202+
}
203+
204+
/// Adds an entry in the mapping from HirIds to PostOrderIds
205+
///
206+
/// Needed so that `add_control_edge_hir_id` can work.
207+
fn add_node_mapping(&mut self, hir_id: HirId, post_order_id: usize) {
208+
self.post_order_map.insert(hir_id, post_order_id);
209+
}
210+
211+
/// Like add_control_edge, but uses a hir_id as the target.
212+
///
213+
/// This can be used for branches where we do not know the PostOrderId of the target yet,
214+
/// such as when handling `break` or `continue`.
215+
fn add_control_edge_hir_id(&mut self, from: usize, to: HirId) {
216+
self.deferred_edges.push((from, to));
217+
}
218+
219+
fn drop_at(&mut self, value: HirId, location: usize) {
220+
let value = self.hidx(value);
221+
self.node_mut(location.into()).drops.push(value);
222+
}
223+
224+
fn reinit_at(&mut self, value: HirId, location: usize) {
225+
let value = match self.hir_id_map.get(&value) {
226+
Some(value) => *value,
227+
// If there's no value, this is never consumed and therefore is never dropped. We can
228+
// ignore this.
229+
None => return,
230+
};
231+
self.node_mut(location.into()).reinits.push(value);
232+
}
233+
}

compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_propagate.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
use std::collections::BTreeMap;
2-
3-
use rustc_index::{bit_set::BitSet, vec::IndexVec};
4-
51
use super::{DropRanges, PostOrderId};
2+
use rustc_index::{bit_set::BitSet, vec::IndexVec};
3+
use std::collections::BTreeMap;
4+
use std::mem::swap;
65

76
impl DropRanges {
87
pub fn propagate_to_fixpoint(&mut self) {
@@ -64,4 +63,18 @@ impl DropRanges {
6463
}
6564
preds
6665
}
66+
67+
/// Looks up PostOrderId for any control edges added by HirId and adds a proper edge for them.
68+
///
69+
/// Should be called after visiting the HIR but before solving the control flow, otherwise some
70+
/// edges will be missed.
71+
fn process_deferred_edges(&mut self) {
72+
let mut edges = vec![];
73+
swap(&mut edges, &mut self.deferred_edges);
74+
edges.into_iter().for_each(|(from, to)| {
75+
let to = *self.post_order_map.get(&to).expect("Expression ID not found");
76+
trace!("Adding deferred edge from {} to {}", from, to);
77+
self.add_control_edge(from, to)
78+
});
79+
}
6780
}

0 commit comments

Comments
 (0)