pub struct ListStore<M: AnyFrameMeta + Repr<MetaSlotSmall>> {
pub regions: MetaRegionOwners,
pub lists: Map<ListId, LinkedListOwner<M>>,
pub loose: Map<LooseId, UniqueFrameOwner<Link<M>>>,
pub cursors: Map<CursorId, CursorOwner<M>>,
}Expand description
One-step-soundness store for the frame LinkedList. Holds the shared
regions, the set of held lists, the pool of loose
(push-eligible) UniqueFrame<Link<M>> handles, and the live cursors.
A cursor checks out its list: a live CursorMut borrows the
LinkedList exclusively, so while a cursor exists its
LinkedListOwner lives inside the CursorOwner (cursors) rather
than in lists. Dropping the cursor returns the list to lists.
Fields§
§regions: MetaRegionOwners§lists: Map<ListId, LinkedListOwner<M>>§loose: Map<LooseId, UniqueFrameOwner<Link<M>>>§cursors: Map<CursorId, CursorOwner<M>>Implementations§
Source§impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> ListStore<M>
impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> ListStore<M>
Sourcepub open spec fn inv(self) -> bool
pub open spec fn inv(self) -> bool
{
&&& self.regions.inv()
&&& forall |id: ListId| {
#[trigger] self.lists.dom().contains(id)
==> {
&&& self.lists[id].inv()
&&& self.lists[id].relate_region(self.regions)
}
}
&&& forall |lid: LooseId| {
#[trigger] self.loose.dom().contains(lid)
==> {
&&& self.loose[lid].inv()
&&& self.loose[lid].global_inv(self.regions)
&&& self.loose[lid].frame_link_inv(self.regions)
&&& self
.regions
.slot_owners[self.loose[lid].slot_index]
.in_list_perm
.value() == 0
}
}
&&& forall |id1: ListId, id2: ListId| {
self.lists.dom().contains(id1) && self.lists.dom().contains(id2)
&& self.lists[id1].list_id == self.lists[id2].list_id
&& self.lists[id1].list_id != 0 ==> id1 == id2
}
&&& forall |lid1: LooseId, lid2: LooseId| {
self.loose.dom().contains(lid1) && self.loose.dom().contains(lid2)
&& self.loose[lid1].slot_index == self.loose[lid2].slot_index
==> lid1 == lid2
}
&&& self.lists.dom().disjoint(self.cursors.dom())
&&& forall |cid: CursorId| {
#[trigger] self.cursors.dom().contains(cid)
==> {
&&& self.cursors[cid].list_own.inv()
&&& self.cursors[cid].wf_with_region(self.regions)
}
}
&&& forall |id: ListId, cid: CursorId| {
self.lists.dom().contains(id) && self.cursors.dom().contains(cid)
&& self.lists[id].list_id == self.cursors[cid].list_own.list_id
&& self.lists[id].list_id != 0 ==> false
}
&&& forall |cid1: CursorId, cid2: CursorId| {
self.cursors.dom().contains(cid1) && self.cursors.dom().contains(cid2)
&& self.cursors[cid1].list_own.list_id == self.cursors[cid2].list_own.list_id
&& self.cursors[cid1].list_own.list_id != 0 ==> cid1 == cid2
}
&&& forall |id: ListId| {
#[trigger] self.lists.dom().contains(id)
==> list_registry_ok(self.regions, self.lists[id])
}
&&& forall |cid: CursorId| {
#[trigger] self.cursors.dom().contains(cid)
==> list_registry_ok(self.regions, self.cursors[cid].list_own)
}
}The store’s top-level invariant.
Source§impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> ListStore<M>
impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> ListStore<M>
Sourcepub proof fn step_size(tracked &self, id: ListId) -> res : nat
pub proof fn step_size(tracked &self, id: ListId) -> res : nat
self.inv(),self.lists.dom().contains(id),ensuresres == self.lists[id].list.len(),LinkedList::size: the number of links in list id. A read-only
query — the store is unchanged.
Sourcepub proof fn step_is_empty(tracked &self, id: ListId) -> res : bool
pub proof fn step_is_empty(tracked &self, id: ListId) -> res : bool
self.inv(),self.lists.dom().contains(id),ensuresres <==> self.lists[id].list.len() == 0,LinkedList::is_empty: whether list id has no links. Read-only.
Sourcepub proof fn step_contains(tracked &self, id: ListId, frame: Paddr) -> res : bool
pub proof fn step_contains(tracked &self, id: ListId, frame: Paddr) -> res : bool
self.inv(),self.lists.dom().contains(id),ensuresres
<==> (valid_frame_paddr(frame)
&& exists |i: int| {
0 <= i < self.lists[id].list.len()
&& #[trigger] meta_to_index(self.lists[id].list[i].paddr)
== frame_to_index(frame)
}),LinkedList::contains: whether frame is a link of list id.
Sourcepub proof fn step_list_new(tracked &mut self) -> res : ListId
pub proof fn step_list_new(tracked &mut self) -> res : ListId
old(self).inv(),ensuresfinal(self).inv(),final(self).regions == old(self).regions,final(self).loose == old(self).loose,!old(self).lists.dom().contains(res),final(self).lists == old(self).lists.insert(res, final(self).lists[res]),final(self).lists[res].list.len() == 0,LinkedList::new: register a fresh empty list.
Sourcepub proof fn step_list_drop(tracked &mut self, id: ListId)
pub proof fn step_list_drop(tracked &mut self, id: ListId)
old(self).inv(),old(self).lists.dom().contains(id),ensuresfinal(self).inv(),!final(self).lists.dom().contains(id),final(self).loose == old(self).loose,final(self).cursors == old(self).cursors,Drop of LinkedList id. Faithful to the verified destructor.
Sourcepub proof fn step_push_front(tracked &mut self, id: ListId, lid: LooseId)
pub proof fn step_push_front(tracked &mut self, id: ListId, lid: LooseId)
old(self).inv(),old(self).lists.dom().contains(id),old(self).loose.dom().contains(lid),ensuresfinal(self).inv(),LinkedList::push_front: move the loose handle lid to the front
of list id. The frame is forgotten into the list (its
drop-obligation consumed); the loose entry is removed.
Sourcepub proof fn step_pop_front(tracked &mut self, id: ListId) -> res : Option<LooseId>
pub proof fn step_pop_front(tracked &mut self, id: ListId) -> res : Option<LooseId>
old(self).inv(),old(self).lists.dom().contains(id),ensuresfinal(self).inv(),old(self).lists[id].list.len() == 0 ==> res is None && *final(self) == *old(self),old(self).lists[id].list.len() > 0 ==> res is Some,LinkedList::pop_front: pop the front link of list id back into
the loose pool as a fresh UniqueFrame<Link<M>>. Requires the
list be non-empty. Returns the fresh loose id.
Sourcepub proof fn step_push_back(tracked &mut self, id: ListId, lid: LooseId)
pub proof fn step_push_back(tracked &mut self, id: ListId, lid: LooseId)
old(self).inv(),old(self).lists.dom().contains(id),old(self).loose.dom().contains(lid),ensuresfinal(self).inv(),LinkedList::push_back: move the loose handle lid to the back
of list id. Same global effect as Self::step_push_front —
only the link’s position within the list differs.
Sourcepub proof fn step_pop_back(tracked &mut self, id: ListId) -> res : Option<LooseId>
pub proof fn step_pop_back(tracked &mut self, id: ListId) -> res : Option<LooseId>
old(self).inv(),old(self).lists.dom().contains(id),ensuresfinal(self).inv(),old(self).lists[id].list.len() == 0 ==> res is None && *final(self) == *old(self),old(self).lists[id].list.len() > 0 ==> res is Some,LinkedList::pop_back: pop the back link of list id back into
the loose pool. Same global effect as Self::step_pop_front —
only which link is removed differs.
Sourcepub proof fn step_insert_before_at(tracked &mut self, id: ListId, n: int, lid: LooseId)
pub proof fn step_insert_before_at(tracked &mut self, id: ListId, n: int, lid: LooseId)
old(self).inv(),old(self).lists.dom().contains(id),old(self).loose.dom().contains(lid),0 <= n <= old(self).lists[id].list.len(),ensuresfinal(self).inv(),The general form of Self::step_push_front /
Self::step_push_back; same global effect.
Sourcepub proof fn step_take_at(tracked &mut self, id: ListId, n: int) -> res : Option<LooseId>
pub proof fn step_take_at(tracked &mut self, id: ListId, n: int) -> res : Option<LooseId>
old(self).inv(),old(self).lists.dom().contains(id),ensuresfinal(self).inv(),!(0 <= n < old(self).lists[id].list.len()) ==> res is None && *final(self) == *old(self),0 <= n < old(self).lists[id].list.len() ==> res is Some,Cursor take_current at an arbitrary position n: pop the link
at index n (0 <= n < len) of list id back into the loose
pool. The general form of Self::step_pop_front /
Self::step_pop_back; same global effect.
Sourcepub proof fn step_cursor_front_mut(tracked &mut self, id: ListId)
pub proof fn step_cursor_front_mut(tracked &mut self, id: ListId)
old(self).inv(),old(self).lists.dom().contains(id),ensuresfinal(self).inv(),!final(self).lists.dom().contains(id),final(self).cursors.dom().contains(id),final(self).cursors[id] == CursorOwner::front_owner(old(self).lists[id]),LinkedList::cursor_front_mut: check list id out into a cursor
positioned at the front (index 0). The list leaves lists and
enters cursors under the same id (its borrow).
Sourcepub proof fn step_cursor_back_mut(tracked &mut self, id: ListId)
pub proof fn step_cursor_back_mut(tracked &mut self, id: ListId)
old(self).inv(),old(self).lists.dom().contains(id),ensuresfinal(self).inv(),!final(self).lists.dom().contains(id),final(self).cursors.dom().contains(id),final(self).cursors[id] == CursorOwner::back_owner(old(self).lists[id]),LinkedList::cursor_back_mut: check list id out into a cursor
at the back (the last element, or the ghost slot when empty).
Sourcepub proof fn step_cursor_mut_at(tracked &mut self, id: ListId, frame: Paddr) -> res : bool
pub proof fn step_cursor_mut_at(tracked &mut self, id: ListId, frame: Paddr) -> res : bool
old(self).inv(),old(self).lists.dom().contains(id),ensuresfinal(self).inv(),res
== (exists |i: int| {
0 <= i < old(self).lists[id].list.len()
&& #[trigger] meta_to_index(old(self).lists[id].list[i].paddr)
== frame_to_index(frame)
}),res
==> !final(self).lists.dom().contains(id) && final(self).cursors.dom().contains(id)
&& exists |i: int| {
0 <= i < old(self).lists[id].list.len()
&& #[trigger] meta_to_index(old(self).lists[id].list[i].paddr)
== #[trigger] frame_to_index(frame)
&& final(self).cursors[id]
== CursorOwner::cursor_mut_at_owner(old(self).lists[id], i)
},!res ==> *final(self) == *old(self),LinkedList::cursor_mut_at.
Sourcepub proof fn step_move_next(tracked &mut self, id: CursorId)
pub proof fn step_move_next(tracked &mut self, id: CursorId)
old(self).inv(),old(self).cursors.dom().contains(id),ensuresfinal(self).inv(),final(self).regions == old(self).regions,final(self).cursors[id] == old(self).cursors[id].move_next_owner_spec(),CursorMut::move_next.
Sourcepub proof fn step_move_prev(tracked &mut self, id: CursorId)
pub proof fn step_move_prev(tracked &mut self, id: CursorId)
old(self).inv(),old(self).cursors.dom().contains(id),ensuresfinal(self).inv(),final(self).regions == old(self).regions,final(self).cursors[id] == old(self).cursors[id].move_prev_owner_spec(),CursorMut::move_prev.
Sourcepub proof fn step_current_meta(tracked &self, id: CursorId) -> res : Option<LinkOwner>
pub proof fn step_current_meta(tracked &self, id: CursorId) -> res : Option<LinkOwner>
self.inv(),self.cursors.dom().contains(id),ensuresres == self.cursors[id].current(),res.is_some() <==> 0 <= self.cursors[id].index < self.cursors[id].length(),CursorMut::current_meta.
Sourcepub proof fn step_as_list(tracked &self, id: CursorId) -> res : Seq<LinkOwner>
pub proof fn step_as_list(tracked &self, id: CursorId) -> res : Seq<LinkOwner>
self.inv(),self.cursors.dom().contains(id),ensuresres == self.cursors[id].list_own.list,res.len() == self.cursors[id].length(),CursorMut::as_list: borrow the cursor’s checked-out list for
reading. A pure no-op.
Sourcepub proof fn step_cursor_drop(tracked &mut self, id: CursorId)
pub proof fn step_cursor_drop(tracked &mut self, id: CursorId)
old(self).inv(),old(self).cursors.dom().contains(id),ensuresfinal(self).inv(),!final(self).cursors.dom().contains(id),final(self).lists.dom().contains(id),final(self).lists[id] == old(self).cursors[id].list_own,Drop of a CursorMut: check the cursor’s list back into lists
under its home id, ending the borrow. Inverse of
Self::step_cursor_front_mut et al.
Sourcepub proof fn step_cursor_insert_before(tracked &mut self, id: CursorId, lid: LooseId)
pub proof fn step_cursor_insert_before(tracked &mut self, id: CursorId, lid: LooseId)
old(self).inv(),old(self).cursors.dom().contains(id),old(self).loose.dom().contains(lid),ensuresfinal(self).inv(),CursorMut::insert_before.
Sourcepub proof fn step_cursor_take_current(tracked &mut self, id: CursorId) -> res : Option<LooseId>
pub proof fn step_cursor_take_current(tracked &mut self, id: CursorId) -> res : Option<LooseId>
old(self).inv(),old(self).cursors.dom().contains(id),ensuresfinal(self).inv(),!(0 <= old(self).cursors[id].index < old(self).cursors[id].length())
==> res is None && *final(self) == *old(self),0 <= old(self).cursors[id].index < old(self).cursors[id].length() ==> res is Some,CursorMut::take_current: through the checked-out cursor id,
Auto Trait Implementations§
impl<M> !RefUnwindSafe for ListStore<M>
impl<M> !UnwindSafe for ListStore<M>
impl<M> Freeze for ListStore<M>
impl<M> Send for ListStore<M>
impl<M> Sync for ListStore<M>
impl<M> Unpin for ListStore<M>
impl<M> UnsafeUnpin for ListStore<M>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Conv for T
impl<T> Conv for T
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
§impl<T, VERUS_SPEC__A> FromSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: From<T>,
impl<T, VERUS_SPEC__A> FromSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: From<T>,
fn obeys_from_spec() -> bool
fn from_spec(v: T) -> VERUS_SPEC__A
§impl<T, VERUS_SPEC__A> IntoSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: Into<T>,
impl<T, VERUS_SPEC__A> IntoSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: Into<T>,
fn obeys_into_spec() -> bool
fn into_spec(self) -> T
§impl<T, U> IntoSpecImpl<U> for Twhere
U: From<T>,
impl<T, U> IntoSpecImpl<U> for Twhere
U: From<T>,
fn obeys_into_spec() -> bool
fn into_spec(self) -> U
§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.impl<A> SpecEq<&A> for Awhere
A: ?Sized,
impl<A> SpecEq<&mut A> for Awhere
A: ?Sized,
impl<A> SpecEq<A> for Awhere
A: ?Sized,
impl<A> SpecEq<Ghost<A>> for A
impl<A> SpecEq<Tracked<A>> for A
§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.