fn access(
        &mut self,
        access: AccessKind,
        tag: SbTag,
        (alloc_id, range, offset): (AllocId, AllocRange, Size), // just for debug printing and error messages
        global: &GlobalState,
    ) -> InterpResult<'tcx> {
        // Two main steps: Find granting item, remove incompatible items above.

        // Step 1: Find granting item.
        let granting_idx = self
            .find_granting(access, tag)
            .ok_or_else(|| self.access_error(access, tag, alloc_id, range, offset))?;

        // Step 2: Remove incompatible items above them.  Make sure we do not remove protected
        // items.  Behavior differs for reads and writes.
        if access == AccessKind::Write {
            // Remove everything above the write-compatible items, like a proper stack. This makes sure read-only and unique
            // pointers become invalid on write accesses (ensures F2a, and ensures U2 for write accesses).
            let first_incompatible_idx = self.find_first_write_incompatible(granting_idx);
            for item in self.borrows.drain(first_incompatible_idx..).rev() {
                trace!("access: popping item {:?}", item);
                Stack::check_protector(&item, Some((tag, access)), global)?;
            }
        } else {
            // On a read, *disable* all `Unique` above the granting item.  This ensures U2 for read accesses.
            // The reason this is not following the stack discipline (by removing the first Unique and
            // everything on top of it) is that in `let raw = &mut *x as *mut _; let _val = *x;`, the second statement
            // would pop the `Unique` from the reborrow of the first statement, and subsequently also pop the
            // `SharedReadWrite` for `raw`.
            // This pattern occurs a lot in the standard library: create a raw pointer, then also create a shared
            // reference and use that.
            // We *disable* instead of removing `Unique` to avoid "connecting" two neighbouring blocks of SRWs.
            for idx in ((granting_idx + 1)..self.borrows.len()).rev() {
                let item = &mut self.borrows[idx];
                if item.perm == Permission::Unique {
                    trace!("access: disabling item {:?}", item);
                    Stack::check_protector(item, Some((tag, access)), global)?;
                    item.perm = Permission::Disabled;
                }
            }
        }

        // Done.
        Ok(())
    }
/// Test if a memory `access` using pointer tagged `tag` is granted.
/// If yes, return the index of the item that granted it.
/// `range` refers the entire operation, and `offset` refers to the specific offset into the
/// allocation that we are currently checking.
Test if a memory `access` using pointer tagged `tag` is granted.
If yes, return the index of the item that granted it.
`range` refers the entire operation, and `offset` refers to the specific offset into the
allocation that we are currently checking.
Test if a memory ` access ` using pointer tagged ` tag ` is granted . If yes return the index of the item that granted it . ` range ` refers the entire operation and ` offset ` refers to the specific offset into the allocation that we are currently checking .
fn access(
        &mut self,
        access: AccessKind,
        tag: SbTag,
        (alloc_id, range, offset): (AllocId, AllocRange, Size), // just for debug printing and error messages
        global: &GlobalState,
    ) -> InterpResult<'tcx> {
        // Two main steps: Find granting item, remove incompatible items above.
        // Step 1: Find granting item.
        let granting_idx = self
            .find_granting(access, tag)
            .ok_or_else(|| self.access_error(access, tag, alloc_id, range, offset))?;
        // Step 2: Remove incompatible items above them.  Make sure we do not remove protected
        // items.  Behavior differs for reads and writes.
        if access == AccessKind::Write {
            // Remove everything above the write-compatible items, like a proper stack. This makes sure read-only and unique
            // pointers become invalid on write accesses (ensures F2a, and ensures U2 for write accesses).
            let first_incompatible_idx = self.find_first_write_incompatible(granting_idx);
            for item in self.borrows.drain(first_incompatible_idx..).rev() {
                trace!("access: popping item {:?}", item);
                Stack::check_protector(&item, Some((tag, access)), global)?;
            }
        } else {
            // On a read, *disable* all `Unique` above the granting item.  This ensures U2 for read accesses.
            // The reason this is not following the stack discipline (by removing the first Unique and
            // everything on top of it) is that in `let raw = &mut *x as *mut _; let _val = *x;`, the second statement
            // would pop the `Unique` from the reborrow of the first statement, and subsequently also pop the
            // `SharedReadWrite` for `raw`.
            // This pattern occurs a lot in the standard library: create a raw pointer, then also create a shared
            // reference and use that.
            // We *disable* instead of removing `Unique` to avoid "connecting" two neighbouring blocks of SRWs.
            for idx in ((granting_idx + 1)..self.borrows.len()).rev() {
                let item = &mut self.borrows[idx];
                if item.perm == Permission::Unique {
                    trace!("access: disabling item {:?}", item);
                    Stack::check_protector(item, Some((tag, access)), global)?;
                    item.perm = Permission::Disabled;
                }
            }
        }
        // Done.
        Ok(())
    }
fn access ( & mut self , access : AccessKind , tag : SbTag , ( alloc_id , range , offset ) : ( AllocId , AllocRange , Size ) , // just for debug printing and error messages global : & GlobalState , ) -> InterpResult < ' tcx > { // Two main steps: Find granting item, remove incompatible items above. // Step 1: Find granting item. let granting_idx = self . find_granting ( access , tag ) . ok_or_else ( | | self . access_error ( access , tag , alloc_id , range , offset ) ) ? ; // Step 2: Remove incompatible items above them.  Make sure we do not remove protected // items.  Behavior differs for reads and writes. if access == AccessKind :: Write { // Remove everything above the write-compatible items, like a proper stack. This makes sure read-only and unique // pointers become invalid on write accesses (ensures F2a, and ensures U2 for write accesses). let first_incompatible_idx = self . find_first_write_incompatible ( granting_idx ) ; for item in self . borrows . drain ( first_incompatible_idx .. ) . rev ( ) { trace ! ( " " item ) ; Stack :: check_protector ( & item , Some ( ( tag , access ) ) , global ) ? ; } } else { // On a read, *disable* all `Unique` above the granting item.  This ensures U2 for read accesses. // The reason this is not following the stack discipline (by removing the first Unique and // everything on top of it) is that in `let raw = &mut *x as *mut _; let _val = *x;`, the second statement // would pop the `Unique` from the reborrow of the first statement, and subsequently also pop the // `SharedReadWrite` for `raw`. // This pattern occurs a lot in the standard library: create a raw pointer, then also create a shared // reference and use that. // We *disable* instead of removing `Unique` to avoid "connecting" two neighbouring blocks of SRWs. for idx in ( ( granting_idx + 1 ) .. self . borrows . len ( ) ) . rev ( ) { let item = & mut self . borrows [ idx ] ; if item . perm == Permission :: Unique { trace ! ( " " item ) ; Stack :: check_protector ( item , Some ( ( tag , access ) ) , global ) ? ; item . perm = Permission :: Disabled ; } } } // Done. Ok ( ( ) ) }
Test if a memory `access` using pointer tagged `tag` is granted.
Test if a memory ` access ` using pointer tagged ` tag ` is granted .
&mut self
access
AccessKind
tag
(AllocId, AllocRange, Size)
global
&GlobalState