fn for_each_reachable_exclusive_permission(
        &mut self,
        object: Object,
        mut revoke_op: impl FnMut(&mut Self, Permission),
    ) {
        let mut reachable = vec![];
        let mut queue = vec![object];

        // Do a depth-first search and accumulate all exclusive permissions
        // reachable from `object` into `reachable`.
        //
        // We can't invoke `op` on them directly since we are holding a
        // reference onto `self.machine` to do the iteration:
        // since `op` can modify the machine state, this ensures that the
        // set of permissions we mutate will be a "snapshot" of how things
        // were at the time of the read (although I don't *believe* that
        // `op` can ever affect any of the permissions that we are traversing
        // here).
        while let Some(o) = queue.pop() {
            tracing::trace!("tracing(o = {:?})", o);
            match &self.machine[o] {
                ObjectData::Instance(instance) => {
                    self.push_reachable_via_fields(&instance.fields, &mut reachable, &mut queue);
                }

                ObjectData::ThunkFn(v) => {
                    self.push_reachable_via_fields(&v.arguments, &mut reachable, &mut queue);
                }

                ObjectData::Tuple(v) => {
                    self.push_reachable_via_fields(&v.fields, &mut reachable, &mut queue);
                }

                ObjectData::Bool(_)
                | ObjectData::Class(_)
                | ObjectData::Float(_)
                | ObjectData::Function(_)
                | ObjectData::Intrinsic(_)
                | ObjectData::Int(_)
                | ObjectData::String(_)
                | ObjectData::ThunkRust(_)
                | ObjectData::Unit(_)
                | ObjectData::Uint(_) => {}
            }
        }

        for p in reachable {
            revoke_op(self, p);
        }
    }
/// Whenever an object is accessed (whether via a read or a write),
/// that counts as an access to any content that is accessible
/// via that object for the purposes of permission accounting.
/// This function invokes `op` on each such permission.
///
/// Note that merely *traversing* an object is not accessing it.
/// Writing `print(a.b.c)` reads all the data from `c`, but
/// only traverses `a.b`.
///
/// # Examples
///
/// This fragment of code
///
/// ```notrust
/// p = MyPair(a: MyPair(a: MyObject(), b: 44), c: 66)
/// q = p.a.b.lease
/// r = p.a.a.lease
/// ```
///
/// creates this object graph
///
/// ```notrust
/// p -my-> [ MyPair ]
///         [   a    ] --my--> [ MyPair ]
///         [        ]         [   a    ] --my--------> [ MyObject ]
///         [        ]         [   b    ] --our--> 44   ^
///         [        ]                              ^   |
///         [   b    ] --our-> 66                   |   |
///                                                 |   |
///                                                 |   |
/// q -leased (joint)-------------------------------+   |
/// r -leased (exclusive)-------------------------------+
/// ```
///
/// Now consider what happens if `s = p.a.share` is executed.
/// The actual path `p.a` does not traverse any leases,
/// but the data in `q` and `r` is now reachable from `s`
/// (in addition to `p.a`).
///
/// In the case of `q`, the reachable data (44) is via a joint path,
/// so adding a new path (via `s`) doesn't make any difference.
///
/// But in the case of `r`, the exclusive lease has to be canceled
/// in order to make way for the new lease to `s`.
Whenever an object is accessed (whether via a read or a write),
that counts as an access to any content that is accessible
via that object for the purposes of permission accounting.
This function invokes `op` on each such permission.

Note that merely *traversing* an object is not accessing it.
Whenever an object is accessed ( whether via a read or a write ) that counts as an access to any content that is accessible via that object for the purposes of permission accounting . This function invokes ` op ` on each such permission . Note that merely * traversing * an object is not accessing it .
fn for_each_reachable_exclusive_permission(
        &mut self,
        object: Object,
        mut revoke_op: impl FnMut(&mut Self, Permission),
    ) {
        let mut reachable = vec![];
        let mut queue = vec![object];
        // Do a depth-first search and accumulate all exclusive permissions
        // reachable from `object` into `reachable`.
        //
        // We can't invoke `op` on them directly since we are holding a
        // reference onto `self.machine` to do the iteration:
        // since `op` can modify the machine state, this ensures that the
        // set of permissions we mutate will be a "snapshot" of how things
        // were at the time of the read (although I don't *believe* that
        // `op` can ever affect any of the permissions that we are traversing
        // here).
        while let Some(o) = queue.pop() {
            tracing::trace!("tracing(o = {:?})", o);
            match &self.machine[o] {
                ObjectData::Instance(instance) => {
                    self.push_reachable_via_fields(&instance.fields, &mut reachable, &mut queue);
                }
                ObjectData::ThunkFn(v) => {
                    self.push_reachable_via_fields(&v.arguments, &mut reachable, &mut queue);
                }
                ObjectData::Tuple(v) => {
                    self.push_reachable_via_fields(&v.fields, &mut reachable, &mut queue);
                }
                ObjectData::Bool(_)
                | ObjectData::Class(_)
                | ObjectData::Float(_)
                | ObjectData::Function(_)
                | ObjectData::Intrinsic(_)
                | ObjectData::Int(_)
                | ObjectData::String(_)
                | ObjectData::ThunkRust(_)
                | ObjectData::Unit(_)
                | ObjectData::Uint(_) => {}
            }
        }
        for p in reachable {
            revoke_op(self, p);
        }
    }
fn for_each_reachable_exclusive_permission ( & mut self , object : Object , mut revoke_op : impl FnMut ( & mut Self , Permission ) , ) { let mut reachable = vec ! [ ] ; let mut queue = vec ! [ object ] ; // Do a depth-first search and accumulate all exclusive permissions // reachable from `object` into `reachable`. // // We can't invoke `op` on them directly since we are holding a // reference onto `self.machine` to do the iteration: // since `op` can modify the machine state, this ensures that the // set of permissions we mutate will be a "snapshot" of how things // were at the time of the read (although I don't *believe* that // `op` can ever affect any of the permissions that we are traversing // here). while let Some ( o ) = queue . pop ( ) { tracing :: trace ! ( " " o ) ; match & self . machine [ o ] { ObjectData :: Instance ( instance ) => { self . push_reachable_via_fields ( & instance . fields , & mut reachable , & mut queue ) ; } ObjectData :: ThunkFn ( v ) => { self . push_reachable_via_fields ( & v . arguments , & mut reachable , & mut queue ) ; } ObjectData :: Tuple ( v ) => { self . push_reachable_via_fields ( & v . fields , & mut reachable , & mut queue ) ; } ObjectData :: Bool ( _ ) | ObjectData :: Class ( _ ) | ObjectData :: Float ( _ ) | ObjectData :: Function ( _ ) | ObjectData :: Intrinsic ( _ ) | ObjectData :: Int ( _ ) | ObjectData :: String ( _ ) | ObjectData :: ThunkRust ( _ ) | ObjectData :: Unit ( _ ) | ObjectData :: Uint ( _ ) => { } } } for p in reachable { revoke_op ( self , p ) ; } }
Whenever an object is accessed (whether via a read or a write),
that counts as an access to any content that is accessible
via that object for the purposes of permission accounting.
Whenever an object is accessed ( whether via a read or a write ) that counts as an access to any content that is accessible via that object for the purposes of permission accounting .
&mut self
object
Object
revoke_op
impl FnMut(&mut Self, Permission)
&mut self
object
Object
revoke_op
impl FnMut(&mut Self, Permission)
examples
This fragment of code



creates this object graph



Now consider what happens if `s = p.a.share` is executed.
The actual path `p.a` does not traverse any leases,
but the data in `q` and `r` is now reachable from `s`
(in addition to `p.a`).

In the case of `q`, the reachable data (44) is via a joint path,
so adding a new path (via `s`) doesn't make any difference.

But in the case of `r`, the exclusive lease has to be canceled
in order to make way for the new lease to `s`.
This fragment of code creates this object graph Now consider what happens if ` s = p . a . share ` is executed . The actual path ` p . a ` does not traverse any leases but the data in ` q ` and ` r ` is now reachable from ` s ` ( in addition to ` p . a ` ) . In the case of ` q ` the reachable data ( 44 ) is via a joint path so adding a new path ( via ` s ` ) doesn ' t make any difference . But in the case of ` r ` the exclusive lease has to be canceled in order to make way for the new lease to ` s ` .