Skip to content

Commit 78c5644

Browse files
committed
drop_ranges: Add TrackedValue enum
This makes it clearer what values we are tracking and why.
1 parent 887e843 commit 78c5644

File tree

3 files changed

+106
-67
lines changed

3 files changed

+106
-67
lines changed

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

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@ use self::record_consumed_borrow::find_consumed_and_borrowed;
1717
use crate::check::FnCtxt;
1818
use hir::def_id::DefId;
1919
use hir::{Body, HirId, HirIdMap, Node};
20+
use rustc_data_structures::fx::FxHashMap;
2021
use rustc_hir as hir;
2122
use rustc_index::bit_set::BitSet;
2223
use rustc_index::vec::IndexVec;
24+
use rustc_middle::hir::place::{PlaceBase, PlaceWithHirId};
25+
use rustc_middle::ty;
2326
use std::collections::BTreeMap;
2427
use std::fmt::Debug;
2528

@@ -47,21 +50,25 @@ pub fn compute_drop_ranges<'a, 'tcx>(
4750

4851
drop_ranges.propagate_to_fixpoint();
4952

50-
DropRanges { hir_id_map: drop_ranges.hir_id_map, nodes: drop_ranges.nodes }
53+
DropRanges { tracked_value_map: drop_ranges.tracked_value_map, nodes: drop_ranges.nodes }
5154
}
5255

5356
/// Applies `f` to consumable portion of a HIR node.
5457
///
5558
/// The `node` parameter should be the result of calling `Map::find(place)`.
56-
fn for_each_consumable(place: HirId, node: Option<Node<'_>>, mut f: impl FnMut(HirId)) {
59+
fn for_each_consumable(
60+
place: TrackedValue,
61+
node: Option<Node<'_>>,
62+
mut f: impl FnMut(TrackedValue),
63+
) {
5764
f(place);
5865
if let Some(Node::Expr(expr)) = node {
5966
match expr.kind {
6067
hir::ExprKind::Path(hir::QPath::Resolved(
6168
_,
6269
hir::Path { res: hir::def::Res::Local(hir_id), .. },
6370
)) => {
64-
f(*hir_id);
71+
f(TrackedValue::Variable(*hir_id));
6572
}
6673
_ => (),
6774
}
@@ -75,22 +82,60 @@ rustc_index::newtype_index! {
7582
}
7683

7784
rustc_index::newtype_index! {
78-
pub struct HirIdIndex {
85+
pub struct TrackedValueIndex {
7986
DEBUG_FORMAT = "hidx({})",
8087
}
8188
}
8289

90+
/// Identifies a value whose drop state we need to track.
91+
#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
92+
enum TrackedValue {
93+
/// Represents a named variable, such as a let binding, parameter, or upvar.
94+
///
95+
/// The HirId points to the variable's definition site.
96+
Variable(HirId),
97+
/// A value produced as a result of an expression.
98+
///
99+
/// The HirId points to the expression that returns this value.
100+
Temporary(HirId),
101+
}
102+
103+
impl TrackedValue {
104+
fn hir_id(&self) -> HirId {
105+
match self {
106+
TrackedValue::Variable(hir_id) | TrackedValue::Temporary(hir_id) => *hir_id,
107+
}
108+
}
109+
}
110+
111+
impl From<&PlaceWithHirId<'_>> for TrackedValue {
112+
fn from(place_with_id: &PlaceWithHirId<'_>) -> Self {
113+
match place_with_id.place.base {
114+
PlaceBase::Rvalue | PlaceBase::StaticItem => {
115+
TrackedValue::Temporary(place_with_id.hir_id)
116+
}
117+
PlaceBase::Local(hir_id)
118+
| PlaceBase::Upvar(ty::UpvarId { var_path: ty::UpvarPath { hir_id }, .. }) => {
119+
TrackedValue::Variable(hir_id)
120+
}
121+
}
122+
}
123+
}
124+
83125
pub struct DropRanges {
84-
hir_id_map: HirIdMap<HirIdIndex>,
126+
tracked_value_map: FxHashMap<TrackedValue, TrackedValueIndex>,
85127
nodes: IndexVec<PostOrderId, NodeInfo>,
86128
}
87129

88130
impl DropRanges {
89131
pub fn is_dropped_at(&self, hir_id: HirId, location: usize) -> bool {
90-
self.hir_id_map
91-
.get(&hir_id)
92-
.copied()
93-
.map_or(false, |hir_id| self.expect_node(location.into()).drop_state.contains(hir_id))
132+
self.tracked_value_map
133+
.get(&TrackedValue::Temporary(hir_id))
134+
.or(self.tracked_value_map.get(&TrackedValue::Variable(hir_id)))
135+
.cloned()
136+
.map_or(false, |tracked_value_id| {
137+
self.expect_node(location.into()).drop_state.contains(tracked_value_id)
138+
})
94139
}
95140

96141
/// Returns a reference to the NodeInfo for a node, panicking if it does not exist
@@ -118,7 +163,7 @@ struct DropRangesBuilder {
118163
/// (see NodeInfo::drop_state). The hir_id_map field stores the mapping
119164
/// from HirIds to the HirIdIndex that is used to represent that value in
120165
/// bitvector.
121-
hir_id_map: HirIdMap<HirIdIndex>,
166+
tracked_value_map: FxHashMap<TrackedValue, TrackedValueIndex>,
122167

123168
/// When building the control flow graph, we don't always know the
124169
/// post-order index of the target node at the point we encounter it.
@@ -138,7 +183,7 @@ struct DropRangesBuilder {
138183
impl Debug for DropRangesBuilder {
139184
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
140185
f.debug_struct("DropRanges")
141-
.field("hir_id_map", &self.hir_id_map)
186+
.field("hir_id_map", &self.tracked_value_map)
142187
.field("post_order_maps", &self.post_order_map)
143188
.field("nodes", &self.nodes.iter_enumerated().collect::<BTreeMap<_, _>>())
144189
.finish()
@@ -154,7 +199,7 @@ impl Debug for DropRangesBuilder {
154199
impl DropRangesBuilder {
155200
/// Returns the number of values (hir_ids) that are tracked
156201
fn num_values(&self) -> usize {
157-
self.hir_id_map.len()
202+
self.tracked_value_map.len()
158203
}
159204

160205
fn node_mut(&mut self, id: PostOrderId) -> &mut NodeInfo {
@@ -177,13 +222,13 @@ struct NodeInfo {
177222
successors: Vec<PostOrderId>,
178223

179224
/// List of hir_ids that are dropped by this node.
180-
drops: Vec<HirIdIndex>,
225+
drops: Vec<TrackedValueIndex>,
181226

182227
/// List of hir_ids that are reinitialized by this node.
183-
reinits: Vec<HirIdIndex>,
228+
reinits: Vec<TrackedValueIndex>,
184229

185230
/// Set of values that are definitely dropped at this point.
186-
drop_state: BitSet<HirIdIndex>,
231+
drop_state: BitSet<TrackedValueIndex>,
187232
}
188233

189234
impl NodeInfo {

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

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
use super::{
22
for_each_consumable, record_consumed_borrow::ConsumedAndBorrowedPlaces, DropRangesBuilder,
3-
HirIdIndex, NodeInfo, PostOrderId,
3+
NodeInfo, PostOrderId, TrackedValue, TrackedValueIndex,
44
};
55
use hir::{
66
intravisit::{self, NestedVisitorMap, Visitor},
7-
Body, Expr, ExprKind, Guard, HirId, HirIdMap,
7+
Body, Expr, ExprKind, Guard, HirId,
88
};
9+
use rustc_data_structures::fx::FxHashMap;
910
use rustc_hir as hir;
1011
use rustc_index::vec::IndexVec;
1112
use rustc_middle::{
@@ -61,20 +62,20 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
6162
) -> Self {
6263
debug!("consumed_places: {:?}", places.consumed);
6364
let drop_ranges = DropRangesBuilder::new(
64-
places.consumed.iter().flat_map(|(_, places)| places.iter().copied()),
65+
places.consumed.iter().flat_map(|(_, places)| places.iter().cloned()),
6566
hir,
6667
num_exprs,
6768
);
6869
Self { hir, places, drop_ranges, expr_index: PostOrderId::from_u32(0), typeck_results, tcx }
6970
}
7071

71-
fn record_drop(&mut self, hir_id: HirId) {
72-
if self.places.borrowed.contains(&hir_id) {
73-
debug!("not marking {:?} as dropped because it is borrowed at some point", hir_id);
72+
fn record_drop(&mut self, value: TrackedValue) {
73+
if self.places.borrowed.contains(&value) {
74+
debug!("not marking {:?} as dropped because it is borrowed at some point", value);
7475
} else {
75-
debug!("marking {:?} as dropped at {:?}", hir_id, self.expr_index);
76+
debug!("marking {:?} as dropped at {:?}", value, self.expr_index);
7677
let count = self.expr_index;
77-
self.drop_ranges.drop_at(hir_id, count);
78+
self.drop_ranges.drop_at(value, count);
7879
}
7980
}
8081

@@ -88,7 +89,9 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
8889
.get(&expr.hir_id)
8990
.map_or(vec![], |places| places.iter().cloned().collect());
9091
for place in places {
91-
for_each_consumable(place, self.hir.find(place), |hir_id| self.record_drop(hir_id));
92+
for_each_consumable(place, self.hir.find(place.hir_id()), |value| {
93+
self.record_drop(value)
94+
});
9295
}
9396
}
9497

@@ -100,7 +103,7 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
100103
{
101104
let location = self.expr_index;
102105
debug!("reinitializing {:?} at {:?}", hir_id, location);
103-
self.drop_ranges.reinit_at(*hir_id, location);
106+
self.drop_ranges.reinit_at(TrackedValue::Variable(*hir_id), location);
104107
} else {
105108
debug!("reinitializing {:?} is not supported", expr);
106109
}
@@ -264,36 +267,40 @@ impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> {
264267
}
265268

266269
impl DropRangesBuilder {
267-
fn new(hir_ids: impl Iterator<Item = HirId>, hir: Map<'_>, num_exprs: usize) -> Self {
268-
let mut hir_id_map = HirIdMap::<HirIdIndex>::default();
270+
fn new(
271+
tracked_values: impl Iterator<Item = TrackedValue>,
272+
hir: Map<'_>,
273+
num_exprs: usize,
274+
) -> Self {
275+
let mut tracked_value_map = FxHashMap::<_, TrackedValueIndex>::default();
269276
let mut next = <_>::from(0u32);
270-
for hir_id in hir_ids {
271-
for_each_consumable(hir_id, hir.find(hir_id), |hir_id| {
272-
if !hir_id_map.contains_key(&hir_id) {
273-
hir_id_map.insert(hir_id, next);
274-
next = <_>::from(next.index() + 1);
277+
for value in tracked_values {
278+
for_each_consumable(value, hir.find(value.hir_id()), |value| {
279+
if !tracked_value_map.contains_key(&value) {
280+
tracked_value_map.insert(value, next);
281+
next = next + 1;
275282
}
276283
});
277284
}
278-
debug!("hir_id_map: {:?}", hir_id_map);
279-
let num_values = hir_id_map.len();
285+
debug!("hir_id_map: {:?}", tracked_value_map);
286+
let num_values = tracked_value_map.len();
280287
Self {
281-
hir_id_map,
288+
tracked_value_map,
282289
nodes: IndexVec::from_fn_n(|_| NodeInfo::new(num_values), num_exprs + 1),
283290
deferred_edges: <_>::default(),
284291
post_order_map: <_>::default(),
285292
}
286293
}
287294

288-
fn hidx(&self, hir_id: HirId) -> HirIdIndex {
289-
*self.hir_id_map.get(&hir_id).unwrap()
295+
fn tracked_value_index(&self, tracked_value: TrackedValue) -> TrackedValueIndex {
296+
*self.tracked_value_map.get(&tracked_value).unwrap()
290297
}
291298

292299
/// Adds an entry in the mapping from HirIds to PostOrderIds
293300
///
294301
/// Needed so that `add_control_edge_hir_id` can work.
295-
fn add_node_mapping(&mut self, hir_id: HirId, post_order_id: PostOrderId) {
296-
self.post_order_map.insert(hir_id, post_order_id);
302+
fn add_node_mapping(&mut self, node_hir_id: HirId, post_order_id: PostOrderId) {
303+
self.post_order_map.insert(node_hir_id, post_order_id);
297304
}
298305

299306
/// Like add_control_edge, but uses a hir_id as the target.
@@ -304,13 +311,13 @@ impl DropRangesBuilder {
304311
self.deferred_edges.push((from, to));
305312
}
306313

307-
fn drop_at(&mut self, value: HirId, location: PostOrderId) {
308-
let value = self.hidx(value);
314+
fn drop_at(&mut self, value: TrackedValue, location: PostOrderId) {
315+
let value = self.tracked_value_index(value);
309316
self.node_mut(location.into()).drops.push(value);
310317
}
311318

312-
fn reinit_at(&mut self, value: HirId, location: PostOrderId) {
313-
let value = match self.hir_id_map.get(&value) {
319+
fn reinit_at(&mut self, value: TrackedValue, location: PostOrderId) {
320+
let value = match self.tracked_value_map.get(&value) {
314321
Some(value) => *value,
315322
// If there's no value, this is never consumed and therefore is never dropped. We can
316323
// ignore this.

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

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
1+
use super::TrackedValue;
12
use crate::{
23
check::FnCtxt,
34
expr_use_visitor::{self, ExprUseVisitor},
45
};
5-
use hir::{def_id::DefId, Body, HirId, HirIdMap, HirIdSet};
6+
use hir::{def_id::DefId, Body, HirId, HirIdMap};
7+
use rustc_data_structures::stable_set::FxHashSet;
68
use rustc_hir as hir;
7-
use rustc_middle::hir::{
8-
map::Map,
9-
place::{Place, PlaceBase},
10-
};
11-
use rustc_middle::ty;
9+
use rustc_middle::hir::map::Map;
1210

13-
pub fn find_consumed_and_borrowed<'a, 'tcx>(
11+
pub(super) fn find_consumed_and_borrowed<'a, 'tcx>(
1412
fcx: &'a FnCtxt<'a, 'tcx>,
1513
def_id: DefId,
1614
body: &'tcx Body<'tcx>,
@@ -20,17 +18,17 @@ pub fn find_consumed_and_borrowed<'a, 'tcx>(
2018
expr_use_visitor.places
2119
}
2220

23-
pub struct ConsumedAndBorrowedPlaces {
21+
pub(super) struct ConsumedAndBorrowedPlaces {
2422
/// Records the variables/expressions that are dropped by a given expression.
2523
///
2624
/// The key is the hir-id of the expression, and the value is a set or hir-ids for variables
2725
/// or values that are consumed by that expression.
2826
///
2927
/// Note that this set excludes "partial drops" -- for example, a statement like `drop(x.y)` is
3028
/// not considered a drop of `x`, although it would be a drop of `x.y`.
31-
pub consumed: HirIdMap<HirIdSet>,
29+
pub(super) consumed: HirIdMap<FxHashSet<TrackedValue>>,
3230
/// A set of hir-ids of values or variables that are borrowed at some point within the body.
33-
pub borrowed: HirIdSet,
31+
pub(super) borrowed: FxHashSet<TrackedValue>,
3432
}
3533

3634
/// Works with ExprUseVisitor to find interesting values for the drop range analysis.
@@ -65,7 +63,7 @@ impl<'tcx> ExprUseDelegate<'tcx> {
6563
.consume_body(body);
6664
}
6765

68-
fn mark_consumed(&mut self, consumer: HirId, target: HirId) {
66+
fn mark_consumed(&mut self, consumer: HirId, target: TrackedValue) {
6967
if !self.places.consumed.contains_key(&consumer) {
7068
self.places.consumed.insert(consumer, <_>::default());
7169
}
@@ -87,8 +85,7 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> {
8785
"consume {:?}; diag_expr_id={:?}, using parent {:?}",
8886
place_with_id, diag_expr_id, parent
8987
);
90-
self.mark_consumed(parent, place_with_id.hir_id);
91-
place_hir_id(&place_with_id.place).map(|place| self.mark_consumed(parent, place));
88+
self.mark_consumed(parent, place_with_id.into());
9289
}
9390

9491
fn borrow(
@@ -97,7 +94,7 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> {
9794
_diag_expr_id: HirId,
9895
_bk: rustc_middle::ty::BorrowKind,
9996
) {
100-
place_hir_id(&place_with_id.place).map(|place| self.places.borrowed.insert(place));
97+
self.places.borrowed.insert(place_with_id.into());
10198
}
10299

103100
fn mutate(
@@ -115,13 +112,3 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> {
115112
) {
116113
}
117114
}
118-
119-
/// Gives the hir_id associated with a place if one exists. This is the hir_id that we want to
120-
/// track for a value in the drop range analysis.
121-
fn place_hir_id(place: &Place<'_>) -> Option<HirId> {
122-
match place.base {
123-
PlaceBase::Rvalue | PlaceBase::StaticItem => None,
124-
PlaceBase::Local(hir_id)
125-
| PlaceBase::Upvar(ty::UpvarId { var_path: ty::UpvarPath { hir_id }, .. }) => Some(hir_id),
126-
}
127-
}

0 commit comments

Comments
 (0)