address nits
This commit is contained in:
parent
e34f35edd8
commit
84134c61bc
@ -71,6 +71,12 @@ pub struct FrameState {
|
|||||||
|
|
||||||
impl VisitProvenance for FrameState {
|
impl VisitProvenance for FrameState {
|
||||||
fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
|
fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
|
||||||
|
// Visit all protected tags. At least in Tree Borrows,
|
||||||
|
// protected tags can not be GC'd because they still have
|
||||||
|
// an access coming when the protector ends. Additionally,
|
||||||
|
// the tree compacting mechanism of TB's GC relies on the fact
|
||||||
|
// that all protected tags are marked as live for correctness,
|
||||||
|
// so we _have_ to visit them here.
|
||||||
for (id, tag) in &self.protected_tags {
|
for (id, tag) in &self.protected_tags {
|
||||||
visit(Some(*id), Some(*tag));
|
visit(Some(*id), Some(*tag));
|
||||||
}
|
}
|
||||||
|
@ -288,18 +288,19 @@ pub fn can_be_replaced_by_child(self, child: Self) -> bool {
|
|||||||
(ReservedFrz { .. }, ReservedIM) => false,
|
(ReservedFrz { .. }, ReservedIM) => false,
|
||||||
(ReservedFrz { .. }, _) => true,
|
(ReservedFrz { .. }, _) => true,
|
||||||
// Active can not be replaced by something surviving
|
// Active can not be replaced by something surviving
|
||||||
// foreign reads and then remaining writable
|
// foreign reads and then remaining writable.
|
||||||
(Active, ReservedIM) => false,
|
(Active, ReservedIM) => false,
|
||||||
(Active, ReservedFrz { .. }) => false,
|
(Active, ReservedFrz { .. }) => false,
|
||||||
|
// Replacing a state by itself is always okay, even if the child state is protected.
|
||||||
(Active, Active) => true,
|
(Active, Active) => true,
|
||||||
// Active can be replaced by Frozen, since it is not protected
|
// Active can be replaced by Frozen, since it is not protected.
|
||||||
(Active, Frozen) => true,
|
(Active, Frozen) => true,
|
||||||
(Active, Disabled) => true,
|
(Active, Disabled) => true,
|
||||||
// Frozen can only be replaced by Disabled
|
// Frozen can only be replaced by Disabled (and itself).
|
||||||
(Frozen, Frozen) => true,
|
(Frozen, Frozen) => true,
|
||||||
(Frozen, Disabled) => true,
|
(Frozen, Disabled) => true,
|
||||||
(Frozen, _) => false,
|
(Frozen, _) => false,
|
||||||
// Disabled can not be replaced by anything else
|
// Disabled can not be replaced by anything else.
|
||||||
(Disabled, Disabled) => true,
|
(Disabled, Disabled) => true,
|
||||||
(Disabled, _) => false,
|
(Disabled, _) => false,
|
||||||
}
|
}
|
||||||
|
@ -128,10 +128,10 @@ fn perform_access(
|
|||||||
Ok(transition)
|
Ok(transition)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Like `perform_access`, but ignores the diagnostics, and also is pure.
|
/// Like `perform_access`, but ignores the concrete error cause and also uses state-passing
|
||||||
/// As such, it returns `Some(x)` if the transition succeeded, or `None`
|
/// rather than a mutable reference. As such, it returns `Some(x)` if the transition succeeded,
|
||||||
/// if there was an error.
|
/// or `None` if there was an error.
|
||||||
#[allow(unused)]
|
#[cfg(test)]
|
||||||
fn perform_access_no_fluff(
|
fn perform_access_no_fluff(
|
||||||
mut self,
|
mut self,
|
||||||
access_kind: AccessKind,
|
access_kind: AccessKind,
|
||||||
@ -865,14 +865,18 @@ fn can_be_replaced_by_single_child(
|
|||||||
live: &FxHashSet<BorTag>,
|
live: &FxHashSet<BorTag>,
|
||||||
) -> Option<UniIndex> {
|
) -> Option<UniIndex> {
|
||||||
let node = self.nodes.get(idx).unwrap();
|
let node = self.nodes.get(idx).unwrap();
|
||||||
|
|
||||||
|
// We never want to replace the root node, as it is also kept in `root_ptr_tags`.
|
||||||
if node.children.len() != 1 || live.contains(&node.tag) || node.parent.is_none() {
|
if node.children.len() != 1 || live.contains(&node.tag) || node.parent.is_none() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
// Since protected nodes are never GC'd (see `borrow_tracker::GlobalStateInner::visit_provenance`),
|
// Since protected nodes are never GC'd (see `borrow_tracker::FrameExtra::visit_provenance`),
|
||||||
// we know that `node` is not protected because otherwise `live` would
|
// we know that `node` is not protected because otherwise `live` would
|
||||||
// have contained `node.tag`.
|
// have contained `node.tag`.
|
||||||
let child_idx = node.children[0];
|
let child_idx = node.children[0];
|
||||||
let child = self.nodes.get(child_idx).unwrap();
|
let child = self.nodes.get(child_idx).unwrap();
|
||||||
|
// Check that for that one child, `can_be_replaced_by_child` holds for the permission
|
||||||
|
// on all locations.
|
||||||
for (_, data) in self.rperms.iter_all() {
|
for (_, data) in self.rperms.iter_all() {
|
||||||
let parent_perm =
|
let parent_perm =
|
||||||
data.get(idx).map(|x| x.permission).unwrap_or_else(|| node.default_initial_perm);
|
data.get(idx).map(|x| x.permission).unwrap_or_else(|| node.default_initial_perm);
|
||||||
@ -893,7 +897,6 @@ fn can_be_replaced_by_single_child(
|
|||||||
/// should have no children, but this is not checked, so that nodes
|
/// should have no children, but this is not checked, so that nodes
|
||||||
/// whose children were rotated somewhere else can be deleted without
|
/// whose children were rotated somewhere else can be deleted without
|
||||||
/// having to first modify them to clear that array.
|
/// having to first modify them to clear that array.
|
||||||
/// otherwise (i.e. the GC should have marked it as removable).
|
|
||||||
fn remove_useless_node(&mut self, this: UniIndex) {
|
fn remove_useless_node(&mut self, this: UniIndex) {
|
||||||
// Due to the API of UniMap we must make sure to call
|
// Due to the API of UniMap we must make sure to call
|
||||||
// `UniValMap::remove` for the key of this node on *all* maps that used it
|
// `UniValMap::remove` for the key of this node on *all* maps that used it
|
||||||
@ -950,17 +953,18 @@ fn remove_useless_children(&mut self, root: UniIndex, live: &FxHashSet<BorTag>)
|
|||||||
// Remove all useless children.
|
// Remove all useless children.
|
||||||
children_of_node.retain_mut(|idx| {
|
children_of_node.retain_mut(|idx| {
|
||||||
if self.is_useless(*idx, live) {
|
if self.is_useless(*idx, live) {
|
||||||
// delete it everywhere else
|
// Delete `idx` node everywhere else.
|
||||||
self.remove_useless_node(*idx);
|
self.remove_useless_node(*idx);
|
||||||
// and delete it from children_of_node
|
// And delete it from children_of_node.
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
if let Some(nextchild) = self.can_be_replaced_by_single_child(*idx, live) {
|
if let Some(nextchild) = self.can_be_replaced_by_single_child(*idx, live) {
|
||||||
// delete the in-between child
|
// `nextchild` is our grandchild, and will become our direct child.
|
||||||
|
// Delete the in-between node, `idx`.
|
||||||
self.remove_useless_node(*idx);
|
self.remove_useless_node(*idx);
|
||||||
// set the new child's parent
|
// Set the new child's parent.
|
||||||
self.nodes.get_mut(nextchild).unwrap().parent = Some(*tag);
|
self.nodes.get_mut(nextchild).unwrap().parent = Some(*tag);
|
||||||
// save the new child in children_of_node
|
// Save the new child in children_of_node.
|
||||||
*idx = nextchild;
|
*idx = nextchild;
|
||||||
}
|
}
|
||||||
// retain it
|
// retain it
|
||||||
|
Loading…
Reference in New Issue
Block a user