Skip to content

Commit 5ba70bd

Browse files
committed
Replace tuples in DropTree with named structs
This allows us to use real field names instead of tuple element numbers. Renaming `previous_drops` to `existing_drops_map` clarifies that "previous" was unrelated to drop order.
1 parent fbdac30 commit 5ba70bd

File tree

1 file changed

+64
-43
lines changed
  • compiler/rustc_mir_build/src/build

1 file changed

+64
-43
lines changed

compiler/rustc_mir_build/src/build/scope.rs

+64-43
Original file line numberDiff line numberDiff line change
@@ -203,16 +203,31 @@ const ROOT_NODE: DropIdx = DropIdx::from_u32(0);
203203
/// in `build_mir`.
204204
#[derive(Debug)]
205205
struct DropTree {
206-
/// Drops in the tree.
207-
drops: IndexVec<DropIdx, (DropData, DropIdx)>,
208-
/// Map for finding the inverse of the `next_drop` relation:
209-
///
210-
/// `previous_drops[(drops[i].1, drops[i].0.local, drops[i].0.kind)] == i`
211-
previous_drops: FxHashMap<(DropIdx, Local, DropKind), DropIdx>,
206+
/// Nodes in the drop tree, containing drop data and a link to the next node.
207+
drops: IndexVec<DropIdx, DropNode>,
208+
/// Map for finding the index of an existing node, given its contents.
209+
existing_drops_map: FxHashMap<DropNodeKey, DropIdx>,
212210
/// Edges into the `DropTree` that need to be added once it's lowered.
213211
entry_points: Vec<(DropIdx, BasicBlock)>,
214212
}
215213

214+
/// A single node in the drop tree.
215+
#[derive(Debug)]
216+
struct DropNode {
217+
/// Info about the drop to be performed at this node in the drop tree.
218+
data: DropData,
219+
/// Index of the "next" drop to perform (in drop order, not declaration order).
220+
next: DropIdx,
221+
}
222+
223+
/// Subset of [`DropNode`] used for reverse lookup in a hash table.
224+
#[derive(Debug, PartialEq, Eq, Hash)]
225+
struct DropNodeKey {
226+
next: DropIdx,
227+
local: Local,
228+
kind: DropKind,
229+
}
230+
216231
impl Scope {
217232
/// Whether there's anything to do for the cleanup path, that is,
218233
/// when unwinding through this scope. This includes destructors,
@@ -258,17 +273,22 @@ impl DropTree {
258273
let fake_source_info = SourceInfo::outermost(DUMMY_SP);
259274
let fake_data =
260275
DropData { source_info: fake_source_info, local: Local::MAX, kind: DropKind::Storage };
261-
let drop_idx = DropIdx::MAX;
262-
let drops = IndexVec::from_elem_n((fake_data, drop_idx), 1);
263-
Self { drops, entry_points: Vec::new(), previous_drops: FxHashMap::default() }
276+
let drops = IndexVec::from_raw(vec![DropNode { data: fake_data, next: DropIdx::MAX }]);
277+
Self { drops, entry_points: Vec::new(), existing_drops_map: FxHashMap::default() }
264278
}
265279

266-
fn add_drop(&mut self, drop: DropData, next: DropIdx) -> DropIdx {
280+
/// Adds a node to the drop tree, consisting of drop data and the index of
281+
/// the "next" drop (in drop order), which could be the sentinel [`ROOT_NODE`].
282+
///
283+
/// If there is already an equivalent node in the tree, nothing is added, and
284+
/// that node's index is returned. Otherwise, the new node's index is returned.
285+
fn add_drop(&mut self, data: DropData, next: DropIdx) -> DropIdx {
267286
let drops = &mut self.drops;
268287
*self
269-
.previous_drops
270-
.entry((next, drop.local, drop.kind))
271-
.or_insert_with(|| drops.push((drop, next)))
288+
.existing_drops_map
289+
.entry(DropNodeKey { next, local: data.local, kind: data.kind })
290+
// Create a new node, and also add its index to the map.
291+
.or_insert_with(|| drops.push(DropNode { data, next }))
272292
}
273293

274294
/// Registers `from` as an entry point to this drop tree, at `to`.
@@ -330,7 +350,7 @@ impl DropTree {
330350
let entry_points = &mut self.entry_points;
331351
entry_points.sort();
332352

333-
for (drop_idx, drop_data) in self.drops.iter_enumerated().rev() {
353+
for (drop_idx, drop_node) in self.drops.iter_enumerated().rev() {
334354
if entry_points.last().is_some_and(|entry_point| entry_point.0 == drop_idx) {
335355
let block = *blocks[drop_idx].get_or_insert_with(|| T::make_block(cfg));
336356
needs_block[drop_idx] = Block::Own;
@@ -348,10 +368,10 @@ impl DropTree {
348368
blocks[drop_idx] = blocks[pred];
349369
}
350370
}
351-
if let DropKind::Value = drop_data.0.kind {
352-
needs_block[drop_data.1] = Block::Own;
371+
if let DropKind::Value = drop_node.data.kind {
372+
needs_block[drop_node.next] = Block::Own;
353373
} else if drop_idx != ROOT_NODE {
354-
match &mut needs_block[drop_data.1] {
374+
match &mut needs_block[drop_node.next] {
355375
pred @ Block::None => *pred = Block::Shares(drop_idx),
356376
pred @ Block::Shares(_) => *pred = Block::Own,
357377
Block::Own => (),
@@ -368,34 +388,35 @@ impl DropTree {
368388
cfg: &mut CFG<'tcx>,
369389
blocks: &IndexSlice<DropIdx, Option<BasicBlock>>,
370390
) {
371-
for (drop_idx, drop_data) in self.drops.iter_enumerated().rev() {
391+
for (drop_idx, drop_node) in self.drops.iter_enumerated().rev() {
372392
let Some(block) = blocks[drop_idx] else { continue };
373-
match drop_data.0.kind {
393+
match drop_node.data.kind {
374394
DropKind::Value => {
375395
let terminator = TerminatorKind::Drop {
376-
target: blocks[drop_data.1].unwrap(),
396+
target: blocks[drop_node.next].unwrap(),
377397
// The caller will handle this if needed.
378398
unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
379-
place: drop_data.0.local.into(),
399+
place: drop_node.data.local.into(),
380400
replace: false,
381401
};
382-
cfg.terminate(block, drop_data.0.source_info, terminator);
402+
cfg.terminate(block, drop_node.data.source_info, terminator);
383403
}
384404
// Root nodes don't correspond to a drop.
385405
DropKind::Storage if drop_idx == ROOT_NODE => {}
386406
DropKind::Storage => {
387407
let stmt = Statement {
388-
source_info: drop_data.0.source_info,
389-
kind: StatementKind::StorageDead(drop_data.0.local),
408+
source_info: drop_node.data.source_info,
409+
kind: StatementKind::StorageDead(drop_node.data.local),
390410
};
391411
cfg.push(block, stmt);
392-
let target = blocks[drop_data.1].unwrap();
412+
let target = blocks[drop_node.next].unwrap();
393413
if target != block {
394414
// Diagnostics don't use this `Span` but debuginfo
395415
// might. Since we don't want breakpoints to be placed
396416
// here, especially when this is on an unwind path, we
397417
// use `DUMMY_SP`.
398-
let source_info = SourceInfo { span: DUMMY_SP, ..drop_data.0.source_info };
418+
let source_info =
419+
SourceInfo { span: DUMMY_SP, ..drop_node.data.source_info };
399420
let terminator = TerminatorKind::Goto { target };
400421
cfg.terminate(block, source_info, terminator);
401422
}
@@ -1277,9 +1298,9 @@ fn build_scope_drops<'tcx>(
12771298
// `unwind_to` should drop the value that we're about to
12781299
// schedule. If dropping this value panics, then we continue
12791300
// with the *next* value on the unwind path.
1280-
debug_assert_eq!(unwind_drops.drops[unwind_to].0.local, drop_data.local);
1281-
debug_assert_eq!(unwind_drops.drops[unwind_to].0.kind, drop_data.kind);
1282-
unwind_to = unwind_drops.drops[unwind_to].1;
1301+
debug_assert_eq!(unwind_drops.drops[unwind_to].data.local, drop_data.local);
1302+
debug_assert_eq!(unwind_drops.drops[unwind_to].data.kind, drop_data.kind);
1303+
unwind_to = unwind_drops.drops[unwind_to].next;
12831304

12841305
// If the operand has been moved, and we are not on an unwind
12851306
// path, then don't generate the drop. (We only take this into
@@ -1306,9 +1327,9 @@ fn build_scope_drops<'tcx>(
13061327
}
13071328
DropKind::Storage => {
13081329
if storage_dead_on_unwind {
1309-
debug_assert_eq!(unwind_drops.drops[unwind_to].0.local, drop_data.local);
1310-
debug_assert_eq!(unwind_drops.drops[unwind_to].0.kind, drop_data.kind);
1311-
unwind_to = unwind_drops.drops[unwind_to].1;
1330+
debug_assert_eq!(unwind_drops.drops[unwind_to].data.local, drop_data.local);
1331+
debug_assert_eq!(unwind_drops.drops[unwind_to].data.kind, drop_data.kind);
1332+
unwind_to = unwind_drops.drops[unwind_to].next;
13121333
}
13131334
// Only temps and vars need their storage dead.
13141335
assert!(local.index() > arg_count);
@@ -1338,30 +1359,30 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
13381359
let is_coroutine = self.coroutine.is_some();
13391360

13401361
// Link the exit drop tree to unwind drop tree.
1341-
if drops.drops.iter().any(|(drop, _)| drop.kind == DropKind::Value) {
1362+
if drops.drops.iter().any(|drop_node| drop_node.data.kind == DropKind::Value) {
13421363
let unwind_target = self.diverge_cleanup_target(else_scope, span);
13431364
let mut unwind_indices = IndexVec::from_elem_n(unwind_target, 1);
1344-
for (drop_idx, drop_data) in drops.drops.iter_enumerated().skip(1) {
1345-
match drop_data.0.kind {
1365+
for (drop_idx, drop_node) in drops.drops.iter_enumerated().skip(1) {
1366+
match drop_node.data.kind {
13461367
DropKind::Storage => {
13471368
if is_coroutine {
13481369
let unwind_drop = self
13491370
.scopes
13501371
.unwind_drops
1351-
.add_drop(drop_data.0, unwind_indices[drop_data.1]);
1372+
.add_drop(drop_node.data, unwind_indices[drop_node.next]);
13521373
unwind_indices.push(unwind_drop);
13531374
} else {
1354-
unwind_indices.push(unwind_indices[drop_data.1]);
1375+
unwind_indices.push(unwind_indices[drop_node.next]);
13551376
}
13561377
}
13571378
DropKind::Value => {
13581379
let unwind_drop = self
13591380
.scopes
13601381
.unwind_drops
1361-
.add_drop(drop_data.0, unwind_indices[drop_data.1]);
1382+
.add_drop(drop_node.data, unwind_indices[drop_node.next]);
13621383
self.scopes.unwind_drops.add_entry_point(
13631384
blocks[drop_idx].unwrap(),
1364-
unwind_indices[drop_data.1],
1385+
unwind_indices[drop_node.next],
13651386
);
13661387
unwind_indices.push(unwind_drop);
13671388
}
@@ -1412,10 +1433,10 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
14121433
// prevent drop elaboration from creating drop flags that would have
14131434
// to be captured by the coroutine. I'm not sure how important this
14141435
// optimization is, but it is here.
1415-
for (drop_idx, drop_data) in drops.drops.iter_enumerated() {
1416-
if let DropKind::Value = drop_data.0.kind {
1417-
debug_assert!(drop_data.1 < drops.drops.next_index());
1418-
drops.entry_points.push((drop_data.1, blocks[drop_idx].unwrap()));
1436+
for (drop_idx, drop_node) in drops.drops.iter_enumerated() {
1437+
if let DropKind::Value = drop_node.data.kind {
1438+
debug_assert!(drop_node.next < drops.drops.next_index());
1439+
drops.entry_points.push((drop_node.next, blocks[drop_idx].unwrap()));
14191440
}
14201441
}
14211442
Self::build_unwind_tree(cfg, drops, fn_span, resume_block);

0 commit comments

Comments
 (0)