Skip to content

Commit cb55919

Browse files
committed
Auto merge of #3835 - JoJoDeveloping:tb-fix-stack-overflow, r=RalfJung
Avoid extra copy by using `retain_mut` and moving the deletion into the closure Fixes the FIXME introduced in #3833. Thanks to `@dmitrii-ubskii` for the idea 🙂
2 parents 29526d2 + f7ddcaa commit cb55919

File tree

1 file changed

+24
-21
lines changed
  • src/borrow_tracker/tree_borrows

1 file changed

+24
-21
lines changed

src/borrow_tracker/tree_borrows/tree.rs

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -754,29 +754,32 @@ impl Tree {
754754
// list of remaining children back in.
755755
let mut children_of_node =
756756
mem::take(&mut self.nodes.get_mut(*tag).unwrap().children);
757-
// Remove all useless children, and save them for later.
758-
// The closure needs `&self` and the loop below needs `&mut self`, so we need to `collect`
759-
// in to a temporary list.
760-
let to_remove: Vec<_> =
761-
children_of_node.drain_filter(|x| self.is_useless(*x, live)).collect();
757+
// Remove all useless children.
758+
children_of_node.retain_mut(|idx| {
759+
if self.is_useless(*idx, live) {
760+
// Note: In the rest of this comment, "this node" refers to `idx`.
761+
// This node has no more children (if there were any, they have already been removed).
762+
// It is also unreachable as determined by the GC, so we can remove it everywhere.
763+
// Due to the API of UniMap we must make sure to call
764+
// `UniValMap::remove` for the key of this node on *all* maps that used it
765+
// (which are `self.nodes` and every range of `self.rperms`)
766+
// before we can safely apply `UniKeyMap::remove` to truly remove
767+
// this tag from the `tag_mapping`.
768+
let node = self.nodes.remove(*idx).unwrap();
769+
for (_perms_range, perms) in self.rperms.iter_mut_all() {
770+
perms.remove(*idx);
771+
}
772+
self.tag_mapping.remove(&node.tag);
773+
// now delete it
774+
false
775+
} else {
776+
// do nothing, but retain
777+
true
778+
}
779+
});
762780
// Put back the now-filtered vector.
763781
self.nodes.get_mut(*tag).unwrap().children = children_of_node;
764-
// Now, all that is left is unregistering the children saved in `to_remove`.
765-
for idx in to_remove {
766-
// Note: In the rest of this comment, "this node" refers to `idx`.
767-
// This node has no more children (if there were any, they have already been removed).
768-
// It is also unreachable as determined by the GC, so we can remove it everywhere.
769-
// Due to the API of UniMap we must make sure to call
770-
// `UniValMap::remove` for the key of this node on *all* maps that used it
771-
// (which are `self.nodes` and every range of `self.rperms`)
772-
// before we can safely apply `UniKeyMap::remove` to truly remove
773-
// this tag from the `tag_mapping`.
774-
let node = self.nodes.remove(idx).unwrap();
775-
for (_perms_range, perms) in self.rperms.iter_mut_all() {
776-
perms.remove(idx);
777-
}
778-
self.tag_mapping.remove(&node.tag);
779-
}
782+
780783
// We are done, the parent can continue.
781784
stack.pop();
782785
continue;

0 commit comments

Comments
 (0)