#[repr(transparent)]pub struct Segment<M: AnyFrameMeta + ?Sized> {
pub range: Range<Paddr>,
pub _marker: PhantomData<M>,
}Expand description
A contiguous range of homogeneous physical memory frames.
This is a handle to multiple contiguous frames. It will be more lightweight than owning an array of frame handles.
The ownership is achieved by the reference counting mechanism of frames.
When constructing a Segment, the frame handles are created then
forgotten, leaving the reference count. When dropping a it, the frame
handles are restored and dropped, decrementing the reference count.
All the metadata of the frames are homogeneous, i.e., they are of the same type.
Fields§
§range: Range<Paddr>The physical address range of the segment.
_marker: PhantomData<M>Implementations§
Source§impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> Segment<M>
impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> Segment<M>
Sourcepub exec fn from_unused(
range: Range<Paddr>,
metadata_fn: impl Fn(Paddr) -> (Paddr, M),
) -> res : Result<Self, GetFrameError>
pub exec fn from_unused( range: Range<Paddr>, metadata_fn: impl Fn(Paddr) -> (Paddr, M), ) -> res : Result<Self, GetFrameError>
Tracked(regions): Tracked<&mut MetaRegionOwners>,requiresold(regions).inv(),forall |paddr_in: Paddr| {
(range.start <= paddr_in < range.end && paddr_in % PAGE_SIZE == 0)
==> {
&&& metadata_fn.requires((paddr_in,))
}
},forall |paddr_in: Paddr, paddr_out: Paddr, m: M| {
metadata_fn.ensures((paddr_in,), (paddr_out, m)) ==> paddr_in == paddr_out
},!(range.end <= MAX_PADDR ==> range.start < range.end) ==> may_panic(),ensuresfinal(regions).inv(),r is Err ==> final(regions).frame_obligations == old(regions).frame_obligations,(range.start % PAGE_SIZE != 0 || range.end % PAGE_SIZE != 0)
==> r == Err::<Self, _>(GetFrameError::NotAligned),(range.start % PAGE_SIZE == 0 && range.end % PAGE_SIZE == 0 && range.end > MAX_PADDR)
==> r == Err::<Self, _>(GetFrameError::OutOfBound),r matches Ok(
seg,
) ==> {
&&& seg.start_paddr() == range.start
&&& seg.end_paddr() == range.end
&&& seg.start_paddr() < seg.end_paddr()
&&& seg.invariants(*final(regions))
&&& crate::specs::mm::frame::segment::seg_obligations_minted(
*old(regions),
*final(regions),
range.start,
crate::specs::mm::frame::segment::seg_nframes(range),
)
&&& forall |paddr: Paddr| {
(range.start <= paddr < range.end && paddr % PAGE_SIZE == 0)
==> final(regions).slots.contains_key(frame_to_index(paddr))
}
&&& range.start < range.end <= MAX_PADDR
},Creates a new Segment from unused frames.
The caller must provide a closure to initialize metadata for all the frames.
The closure receives the physical address of the frame and returns the
metadata, which is similar to core::array::from_fn.
It returns an error if:
- the physical address is invalid or not aligned;
- any of the frames cannot be created with a specific reason.
§Panics
It panics if the range is empty.
§Verified Properties
§Preconditions
- the metadata function must be well-formed and valid for all frames in the range;
- the metadata function must ensure that the frames can be created and owned by the segment;
- for any frame created via the closure
metadata_fn, the corresponding slot inregionsmust be unused and not dropped in the owner (MetaRegionOwners).
Range constraints (alignment, range.end <= MAX_PADDR, non-emptiness) are runtime-checked
in the body — see the postconditions below for the corresponding error variants.
§Postconditions
- if the result is
Ok, the returned segment satisfies its invariant, relates to the updated metadata region, and has the same physical address range as the input; - if the input range is misaligned, the result is
Err(NotAligned); - if the input range exceeds
MAX_PADDR, the result isErr(OutOfBound); - if the input is aligned and within
MAX_PADDRand the function terminated, thenrange.start < range.end(the runtimeassert!would otherwise diverge).
Source§impl<M: AnyFrameMeta + ?Sized> Segment<M>
impl<M: AnyFrameMeta + ?Sized> Segment<M>
Sourcepub exec fn start_paddr(&self) -> Paddr
pub exec fn start_paddr(&self) -> Paddr
self.start_paddr(),Gets the start physical address of the contiguous frames.
pub fn __VERUS_SPEC_start_paddr(&self) -> Paddr
Sourcepub exec fn end_paddr(&self) -> Paddr
pub exec fn end_paddr(&self) -> Paddr
self.end_paddr(),Gets the end physical address of the contiguous frames.
pub fn __VERUS_SPEC_end_paddr(&self) -> Paddr
Sourcepub exec fn size(&self) -> r : usize
pub exec fn size(&self) -> r : usize
self.inv(),ensuresr == self.end_paddr() - self.start_paddr(),returnsself.size(),Gets the length in bytes of the contiguous frames.
pub fn __VERUS_SPEC_size(&self) -> usize
Source§impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> Segment<M>
impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> Segment<M>
Sourcepub exec fn split(self, offset: usize) -> r : (Self, Self)
pub exec fn split(self, offset: usize) -> r : (Self, Self)
Tracked(regions): Tracked<&mut MetaRegionOwners>,requiresself.invariants(*old(regions)),offset % PAGE_SIZE != 0 ==> may_panic(),!(0 < offset && offset < self.size()) ==> may_panic(),ensuresfinal(regions).slots == old(regions).slots,final(regions).slot_owners == old(regions).slot_owners,final(regions).frame_obligations == old(regions).frame_obligations,(r.0, r.1) == self.split_spec(offset),r.0.invariants(*final(regions)),r.1.invariants(*final(regions)),Splits the frames into two at the given byte offset from the start.
The resulting frames cannot be empty. So the offset cannot be neither zero nor the length of the frames.
§Verified Properties
§Preconditions
- the segment must satisfy its bundled invariant against the metadata region;
- the offset must be aligned and within bounds;
§Postconditions
- the resulting segments satisfy their bundled invariants;
- they match
Self::split_spec; - both halves continue to relate correctly to
regions(which is unchanged).
Sourcepub open spec fn page_in_range_saturated(
self,
range: &Range<usize>,
regions: MetaRegionOwners,
) -> bool
pub open spec fn page_in_range_saturated( self, range: &Range<usize>, regions: MetaRegionOwners, ) -> bool
{
exists |j: int| {
(range.start as int) / (PAGE_SIZE as int) <= j
< (range.end as int) / (PAGE_SIZE as int)
&& regions
.slot_owners[frame_to_index(
(self.start_paddr() + j * PAGE_SIZE) as usize,
)]
.inner_perms
.ref_count
.value() >= REF_COUNT_MAX
}
}Precise panic condition for Self::slice. slice diverges iff:
- the slice range is misaligned, reversed, or out of the segment’s
bounds (the diverging
assert!s at the top ofslice), or - the specific per-frame slot that
slicebumps is already saturated (inc_ref_countwould overflow). Unlikequerywhich clones one item,slicebumps one refcount per page in the slice range, so the saturation disjunct is an exists over those specific paddrsself.range.start + j * PAGE_SIZEforj ∈ [range.start/PAGE_SIZE, range.end/PAGE_SIZE).
Sourcepub exec fn slice(&self, range: &Range<usize>) -> r : Self
pub exec fn slice(&self, range: &Range<usize>) -> r : Self
Tracked(regions): Tracked<&mut MetaRegionOwners>,requiresself.invariants(*old(regions)),range.start % PAGE_SIZE != 0 ==> may_panic(),range.end % PAGE_SIZE != 0 ==> may_panic(),range.start > range.end ==> may_panic(),range.end > self.size() ==> may_panic(),self.page_in_range_saturated(range, *old(regions)) ==> may_panic(),ensuresrange.start % PAGE_SIZE == 0,range.end % PAGE_SIZE == 0,range.start <= range.end,self.range.start + range.end <= self.range.end,!self.page_in_range_saturated(range, *old(regions)),r.inv(),r.start_paddr() == self.start_paddr() + range.start,r.end_paddr() == self.start_paddr() + range.end,r.end_paddr() <= self.end_paddr(),final(regions).inv(),final(regions).slots == old(regions).slots,final(regions).slot_owners.dom() == old(regions).slot_owners.dom(),final(regions).frame_obligations == old(regions).frame_obligations,Gets an extra handle to the frames in the byte offset range.
The sliced byte offset range in indexed by the offset from the start of the contiguous frames. The resulting frames holds extra reference counts.
§Verified Properties
§Postconditions
- the resulting slice’s range matches the slicing range and is in-bounds
(the in-bounds check follows from the diverging
assert!in the body); regionspreserves invariants and key domains. Per-frame state for a hypothetical sub-segment relation is not exposed; threading that through the per-frame ref-count bump loop would require a much heavier proof. MirrorsSegment::clone.
See also [vstd::seq::Seq::subrange].
Sourcepub open spec fn nrpage_spec(&self) -> usize
pub open spec fn nrpage_spec(&self) -> usize
self.inv(),{ self.size() / PAGE_SIZE }Returns the number of pages of the contiguous frames.
Sourcepub closed spec fn split_spec(self, offset: usize) -> (Self, Self)
pub closed spec fn split_spec(self, offset: usize) -> (Self, Self)
self.inv(),offset % PAGE_SIZE == 0,0 < offset < self.size(),Splits the contiguous frames into two at the given byte offset from the start in spec mode.
Source§impl<M: AnyFrameMeta + Repr<MetaSlotStorage>> Segment<M>
impl<M: AnyFrameMeta + Repr<MetaSlotStorage>> Segment<M>
Sourcepub exec fn drop(self)
pub exec fn drop(self)
Tracked(regions): Tracked<&mut MetaRegionOwners>,requiresself.invariants(*old(regions)),forall |i: int| {
0 <= i < crate::specs::mm::frame::segment::seg_nframes(self.range)
==> {
let idx = frame_to_index((self.range.start + i * PAGE_SIZE) as usize);
old(regions).slot_owners[idx].inner_perms.ref_count.value() == 1
==> {
&&& old(regions).slot_owners[idx].inner_perms.storage.is_init()
&&& old(regions).slot_owners[idx].inner_perms.in_list.value() == 0
}
}
},ensuresfinal(regions).inv(),Verified drop: iterates over each frame in the segment, decrements its reference count, and (when last ref) tears down the metadata.
Per-frame linear-drop: before the teardown loop, this redeems the one
frame_obligations entry the segment retained per frame (minted by
Segment::from_unused). Failing to drop the segment leaves those
per-frame counts outstanding and breaks
MetaRegionOwners::clean_inv at the enclosing function’s exit.
Source§impl<M: AnyUFrameMeta + OwnerOf> Segment<M>
impl<M: AnyUFrameMeta + OwnerOf> Segment<M>
Sourcepub exec fn reader(&self) -> r : VmReader<'_, Infallible>
pub exec fn reader(&self) -> r : VmReader<'_, Infallible>
->
owner: Tracked<VmIoOwner>,requiresself.inv(),ensuresr.inv(),owner@.inv(),r.wf(owner@),r.cursor.vaddr == paddr_to_vaddr_spec(self.start_paddr()),r.remain_spec() == self.size(),owner@.is_kernel,Sourcepub exec fn writer(&self) -> r : VmWriter<'_, Infallible>
pub exec fn writer(&self) -> r : VmWriter<'_, Infallible>
->
owner: Tracked<VmIoOwner>,requiresself.inv(),ensuresr.inv(),owner@.inv(),r.wf(owner@),r.cursor.vaddr == paddr_to_vaddr_spec(self.start_paddr()),r.avail_spec() == self.size(),owner@.is_kernel,!owner@.is_fallible,Source§impl<M: AnyFrameMeta + ?Sized> Segment<M>
impl<M: AnyFrameMeta + ?Sized> Segment<M>
Sourcepub open spec fn relate_regions(&self, regions: MetaRegionOwners) -> bool
pub open spec fn relate_regions(&self, regions: MetaRegionOwners) -> bool
{
&&& forall |i: int| {
0 <= i < seg_nframes(self.range)
==> {
let idx = frame_to_index((self.range.start + i * PAGE_SIZE) as usize);
&&& regions.frame_obligations.count(idx) >= 1
&&& regions.slot_owners.contains_key(idx)
&&& regions.slots.contains_key(idx)
&&& regions.slot_owners[idx].slot_vaddr == index_to_meta(idx)
&&& regions.slot_owners[idx].inner_perms.ref_count.value() > 0
&&& regions.slot_owners[idx].inner_perms.ref_count.value()
<= crate::mm::frame::meta::REF_COUNT_MAX
&&& regions.slot_owners[idx].paths_in_pt.is_empty()
&&& regions.slot_owners[idx].usage is Frame
}
}
&&& forall |i: int, j: int| {
0 <= i < j < seg_nframes(self.range)
==> frame_to_index((self.range.start + i * PAGE_SIZE) as usize)
!= frame_to_index((self.range.start + j * PAGE_SIZE) as usize)
}
}The cross-object relation between a Segment and the global
MetaRegionOwners.
For every frame i in the segment, this asserts:
- the slot owner and canonical slot permission are present in
regions, - the slot’s
slot_vaddris consistent with its index, - the slot has a live, non-
UNUSEDreference count, - the slot has a pending
frame_obligationsentry for this segment, - the slot is a data-frame slot with no page-table paths,
- distinct frames in the segment map to distinct slot indices.
This is an invariant preserved by operations that transform a
Segment together with MetaRegionOwners. The segment’s own range
is the only identity source; there is no separate segment owner token.
Sourcepub proof fn relate_regions_at(&self, regions: MetaRegionOwners, i: int)
pub proof fn relate_regions_at(&self, regions: MetaRegionOwners, i: int)
self.relate_regions(regions),0 <= i < seg_nframes(self.range),ensures({
let idx = frame_to_index((self.range.start + i * PAGE_SIZE) as usize);
&&& regions.frame_obligations.count(idx) >= 1
&&& regions.slot_owners.contains_key(idx)
&&& regions.slots.contains_key(idx)
&&& regions.slot_owners[idx].slot_vaddr == index_to_meta(idx)
&&& regions.slot_owners[idx].inner_perms.ref_count.value() > 0
&&& regions.slot_owners[idx].inner_perms.ref_count.value()
<= crate::mm::frame::meta::REF_COUNT_MAX
&&& regions.slot_owners[idx].paths_in_pt.is_empty()
&&& regions.slot_owners[idx].usage is Frame
}),Manually instantiates the [relate_regions] forall at a specific index.
Use this to extract per-frame facts without fighting trigger inference.
Sourcepub proof fn relate_regions_distinct(&self, regions: MetaRegionOwners, i: int, j: int)
pub proof fn relate_regions_distinct(&self, regions: MetaRegionOwners, i: int, j: int)
self.relate_regions(regions),0 <= i < j < seg_nframes(self.range),ensuresframe_to_index((self.range.start + i * PAGE_SIZE) as usize)
!= frame_to_index((self.range.start + j * PAGE_SIZE) as usize),Manually instantiates the [relate_regions] distinctness forall at a
specific index pair: distinct in-range frames map to distinct slot
indices. Reusable lever for from_unused/split/slice proofs.
Sourcepub open spec fn invariants(&self, regions: MetaRegionOwners) -> bool
pub open spec fn invariants(&self, regions: MetaRegionOwners) -> bool
{
&&& self.inv()
&&& regions.inv()
&&& self.relate_regions(regions)
}The bundled invariant for Segment operations that thread the global
regions: the segment’s own invariant, the region invariant, and the
cross-object relation tying this segment’s range to regions.
Mirrors the invariants bundles used throughout the page-table / cursor
code — it collapses the clauses repeated across split, slice,
into_raw, next, and drop into one predicate.
Sourcepub open spec fn kernel_mem_view_covers(&self, view: &MemView) -> bool
pub open spec fn kernel_mem_view_covers(&self, view: &MemView) -> bool
{
&&& self.inv()
&&& view.mappings_are_disjoint()
&&& forall |vaddr: Vaddr| {
paddr_to_vaddr(self.start_paddr()) <= vaddr
< paddr_to_vaddr(self.start_paddr()) + self.end_paddr() - self.start_paddr()
==> {
&&& view.addr_transl(vaddr) is Some
&&& view.memory.contains_key((view.addr_transl(vaddr)->0).0)
&&& view.memory[(view.addr_transl(vaddr)->0).0].inv()
&&& view
.memory[(view.addr_transl(vaddr)->0).0]
.contents[(view.addr_transl(vaddr)->0).1 as int] is Init
}
}
&&& forall |paddr: Paddr| {
self.start_paddr() <= paddr < self.end_paddr()
==> {
let vaddr = paddr_to_vaddr(paddr);
&&& view.addr_transl(vaddr) is Some
&&& (view.addr_transl(vaddr)->0).0 <= paddr
&&& paddr
< (view.addr_transl(vaddr)->0).0
+ view.memory[(view.addr_transl(vaddr)->0).0].size@
&&& (view.addr_transl(vaddr)->0).1
== paddr - (view.addr_transl(vaddr)->0).0
&&& view.memory.contains_key((view.addr_transl(vaddr)->0).0)
&&& view.memory[(view.addr_transl(vaddr)->0).0].inv()
&&& view
.memory[(view.addr_transl(vaddr)->0).0]
.contents[(view.addr_transl(vaddr)->0).1 as int] is Init
}
}
}Whether a MemView covers the segment through the kernel direct mapping.
This predicate only describes the virtual-to-physical relation and the presence of initialized backing frame contents.
Trait Implementations§
Source§impl<M: AnyFrameMeta + Repr<MetaSlotStorage>> From<Frame<M>> for Segment<M>
impl<M: AnyFrameMeta + Repr<MetaSlotStorage>> From<Frame<M>> for Segment<M>
Source§impl<M: AnyFrameMeta + ?Sized> Inv for Segment<M>
impl<M: AnyFrameMeta + ?Sized> Inv for Segment<M>
Source§open spec fn inv(self) -> bool
open spec fn inv(self) -> bool
{
&&& self.start_paddr() % PAGE_SIZE == 0
&&& self.end_paddr() % PAGE_SIZE == 0
&&& self.start_paddr() <= self.end_paddr() <= MAX_PADDR
}The invariant of a Segment:
- the physical addresses of the frames are aligned and within bounds.
- the range is well-formed, i.e., the start is less than or equal to the end.
Source§impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> Iterator for Segment<M>
impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> Iterator for Segment<M>
Source§fn next_chunk<const N: usize>(
&mut self,
) -> Result<[Self::Item; N], IntoIter<Self::Item, N>>where
Self: Sized,
fn next_chunk<const N: usize>(
&mut self,
) -> Result<[Self::Item; N], IntoIter<Self::Item, N>>where
Self: Sized,
iter_next_chunk)N values. Read more1.0.0 · Source§fn size_hint(&self) -> (usize, Option<usize>)
fn size_hint(&self) -> (usize, Option<usize>)
1.0.0 · Source§fn count(self) -> usizewhere
Self: Sized,
fn count(self) -> usizewhere
Self: Sized,
1.0.0 · Source§fn last(self) -> Option<Self::Item>where
Self: Sized,
fn last(self) -> Option<Self::Item>where
Self: Sized,
Source§fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>>
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>>
iter_advance_by)n elements. Read more1.0.0 · Source§fn nth(&mut self, n: usize) -> Option<Self::Item>
fn nth(&mut self, n: usize) -> Option<Self::Item>
nth element of the iterator. Read more1.28.0 · Source§fn step_by(self, step: usize) -> StepBy<Self>where
Self: Sized,
fn step_by(self, step: usize) -> StepBy<Self>where
Self: Sized,
1.0.0 · Source§fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter>
fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter>
1.0.0 · Source§fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter>where
Self: Sized,
U: IntoIterator,
fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter>where
Self: Sized,
U: IntoIterator,
Source§fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G>
fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G>
iter_intersperse)separator
between items of the original iterator. Read more1.0.0 · Source§fn map<B, F>(self, f: F) -> Map<Self, F>
fn map<B, F>(self, f: F) -> Map<Self, F>
1.0.0 · Source§fn filter<P>(self, predicate: P) -> Filter<Self, P>
fn filter<P>(self, predicate: P) -> Filter<Self, P>
1.0.0 · Source§fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>
fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>
1.0.0 · Source§fn enumerate(self) -> Enumerate<Self>where
Self: Sized,
fn enumerate(self) -> Enumerate<Self>where
Self: Sized,
1.0.0 · Source§fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>
fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>
1.0.0 · Source§fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>
fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>
1.57.0 · Source§fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>
fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>
1.0.0 · Source§fn skip(self, n: usize) -> Skip<Self>where
Self: Sized,
fn skip(self, n: usize) -> Skip<Self>where
Self: Sized,
n elements. Read more1.0.0 · Source§fn take(self, n: usize) -> Take<Self>where
Self: Sized,
fn take(self, n: usize) -> Take<Self>where
Self: Sized,
n elements, or fewer
if the underlying iterator ends sooner. Read more1.0.0 · Source§fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F>
fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F>
Source§fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N>
fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N>
iter_map_windows)f for each contiguous window of size N over
self and returns an iterator over the outputs of f. Like slice::windows(),
the windows during mapping overlap as well. Read more1.0.0 · Source§fn inspect<F>(self, f: F) -> Inspect<Self, F>
fn inspect<F>(self, f: F) -> Inspect<Self, F>
1.0.0 · Source§fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
Iterator. Read moreSource§fn collect_into<E>(self, collection: &mut E) -> &mut E
fn collect_into<E>(self, collection: &mut E) -> &mut E
iter_collect_into)1.0.0 · Source§fn partition<B, F>(self, f: F) -> (B, B)
fn partition<B, F>(self, f: F) -> (B, B)
Source§fn is_partitioned<P>(self, predicate: P) -> bool
fn is_partitioned<P>(self, predicate: P) -> bool
iter_is_partitioned)true precede all those that return false. Read more1.27.0 · Source§fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
1.27.0 · Source§fn try_for_each<F, R>(&mut self, f: F) -> R
fn try_for_each<F, R>(&mut self, f: F) -> R
1.0.0 · Source§fn fold<B, F>(self, init: B, f: F) -> B
fn fold<B, F>(self, init: B, f: F) -> B
1.51.0 · Source§fn reduce<F>(self, f: F) -> Option<Self::Item>
fn reduce<F>(self, f: F) -> Option<Self::Item>
Source§fn try_reduce<R>(
&mut self,
f: impl FnMut(Self::Item, Self::Item) -> R,
) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryType
fn try_reduce<R>( &mut self, f: impl FnMut(Self::Item, Self::Item) -> R, ) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryType
iterator_try_reduce)1.0.0 · Source§fn all<F>(&mut self, f: F) -> bool
fn all<F>(&mut self, f: F) -> bool
1.0.0 · Source§fn any<F>(&mut self, f: F) -> bool
fn any<F>(&mut self, f: F) -> bool
1.0.0 · Source§fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
1.30.0 · Source§fn find_map<B, F>(&mut self, f: F) -> Option<B>
fn find_map<B, F>(&mut self, f: F) -> Option<B>
Source§fn try_find<R>(
&mut self,
f: impl FnMut(&Self::Item) -> R,
) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryType
fn try_find<R>( &mut self, f: impl FnMut(&Self::Item) -> R, ) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryType
try_find)1.0.0 · Source§fn position<P>(&mut self, predicate: P) -> Option<usize>
fn position<P>(&mut self, predicate: P) -> Option<usize>
1.6.0 · Source§fn max_by_key<B, F>(self, f: F) -> Option<Self::Item>
fn max_by_key<B, F>(self, f: F) -> Option<Self::Item>
1.15.0 · Source§fn max_by<F>(self, compare: F) -> Option<Self::Item>
fn max_by<F>(self, compare: F) -> Option<Self::Item>
1.6.0 · Source§fn min_by_key<B, F>(self, f: F) -> Option<Self::Item>
fn min_by_key<B, F>(self, f: F) -> Option<Self::Item>
1.15.0 · Source§fn min_by<F>(self, compare: F) -> Option<Self::Item>
fn min_by<F>(self, compare: F) -> Option<Self::Item>
1.0.0 · Source§fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)
fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)
1.36.0 · Source§fn copied<'a, T>(self) -> Copied<Self>
fn copied<'a, T>(self) -> Copied<Self>
Source§fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N>where
Self: Sized,
fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N>where
Self: Sized,
iter_array_chunks)N elements of the iterator at a time. Read more1.11.0 · Source§fn product<P>(self) -> P
fn product<P>(self) -> P
Source§fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering
fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering
iter_order_by)Iterator with those
of another with respect to the specified comparison function. Read more1.5.0 · Source§fn partial_cmp<I>(self, other: I) -> Option<Ordering>
fn partial_cmp<I>(self, other: I) -> Option<Ordering>
PartialOrd elements of
this Iterator with those of another. The comparison works like short-circuit
evaluation, returning a result without comparing the remaining elements.
As soon as an order can be determined, the evaluation stops and a result is returned. Read moreSource§fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering>where
Self: Sized,
I: IntoIterator,
F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Option<Ordering>,
fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering>where
Self: Sized,
I: IntoIterator,
F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Option<Ordering>,
iter_order_by)Iterator with those
of another with respect to the specified comparison function. Read moreSource§fn eq_by<I, F>(self, other: I, eq: F) -> bool
fn eq_by<I, F>(self, other: I, eq: F) -> bool
iter_order_by)1.5.0 · Source§fn lt<I>(self, other: I) -> bool
fn lt<I>(self, other: I) -> bool
Iterator are lexicographically
less than those of another. Read more1.5.0 · Source§fn le<I>(self, other: I) -> bool
fn le<I>(self, other: I) -> bool
Iterator are lexicographically
less or equal to those of another. Read more1.5.0 · Source§fn gt<I>(self, other: I) -> bool
fn gt<I>(self, other: I) -> bool
Iterator are lexicographically
greater than those of another. Read more1.5.0 · Source§fn ge<I>(self, other: I) -> bool
fn ge<I>(self, other: I) -> bool
Iterator are lexicographically
greater than or equal to those of another. Read more1.82.0 · Source§fn is_sorted_by<F>(self, compare: F) -> bool
fn is_sorted_by<F>(self, compare: F) -> bool
1.82.0 · Source§fn is_sorted_by_key<F, K>(self, f: F) -> bool
fn is_sorted_by_key<F, K>(self, f: F) -> bool
Source§impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> RCClone for Segment<M>
impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> RCClone for Segment<M>
Source§open spec fn clone_requires(self, perm: MetaRegionOwners) -> bool
open spec fn clone_requires(self, perm: MetaRegionOwners) -> bool
{
&&& self.inv()
&&& perm.inv()
&&& forall |pa: Paddr| {
(self.start_paddr() <= pa < self.end_paddr() && pa % PAGE_SIZE == 0)
==> {
let idx = frame_to_index(pa);
&&& perm.slots.contains_key(idx)
&&& valid_frame_paddr(pa)
&&& perm.slot_owners[idx].inner_perms.ref_count.value() > 0
&&& perm.slot_owners[idx].inner_perms.ref_count.value() + 1
< super::meta::REF_COUNT_MAX
&&& !MetaSlot::inc_ref_count_panic_cond(
perm.slot_owners[idx].inner_perms.ref_count,
)
}
}
}Source§open spec fn clone_ensures(
self,
old_perm: MetaRegionOwners,
new_perm: MetaRegionOwners,
res: Self,
) -> bool
open spec fn clone_ensures( self, old_perm: MetaRegionOwners, new_perm: MetaRegionOwners, res: Self, ) -> bool
{
&&& res.range() == self.range()
&&& res.inv()
&&& new_perm.inv()
&&& new_perm.frame_obligations =~= old_perm.frame_obligations
}Source§exec fn clone(&self, Tracked(perm): Tracked<&mut MetaRegionOwners>) -> res : Self
exec fn clone(&self, Tracked(perm): Tracked<&mut MetaRegionOwners>) -> res : Self
Source§impl<M: AnyFrameMeta + ?Sized> TrackDrop for Segment<M>
impl<M: AnyFrameMeta + ?Sized> TrackDrop for Segment<M>
Source§type State = MetaRegionOwners
type State = MetaRegionOwners
The tracked state for ManuallyDrop purposes is the global
MetaRegionOwners. The real per-segment obligation is represented
by one entry per frame in MetaRegionOwners::frame_obligations, not
by this TrackDrop impl. That keeps
ManuallyDrop::new(self) callable in places like
Segment::split / Segment::into_raw where the segment is
“temporarily forgotten” without an actual ledger event.
Source§type Obligation = DropObligation<Range<usize>>
type Obligation = DropObligation<Range<usize>>
Real segment-range key. The token produced by constructor_spec
carries self.range as identity. The mint here does NOT insert
into obligations — the real per-segment entry is added by
Segment::from_unused and removed by Segment::drop directly.
Carrying Range<Paddr> on the token still strengthens the
discipline: a token forged for one segment can’t masquerade as
belonging to another (the consume_requires/drop_requires
checks would refuse the mismatched key).
Source§open spec fn tracked_redeem_requires(self, s: Self::State) -> bool
open spec fn tracked_redeem_requires(self, s: Self::State) -> bool
{ true }Source§open spec fn tracked_redeem_ensures(
self,
s0: Self::State,
s1: Self::State,
obl: Self::Obligation,
) -> bool
open spec fn tracked_redeem_ensures( self, s0: Self::State, s1: Self::State, obl: Self::Obligation, ) -> bool
{
&&& s0 =~= s1
&&& obl.value() == self.range
}Source§proof fn tracked_redeem(self, tracked s: &mut Self::State) -> tracked obl : Self::Obligation
proof fn tracked_redeem(self, tracked s: &mut Self::State) -> tracked obl : Self::Obligation
Source§open spec fn drop_requires(self, s: Self::State, obl: Self::Obligation) -> bool
open spec fn drop_requires(self, s: Self::State, obl: Self::Obligation) -> bool
{
&&& s.inv()
&&& obl.value() == self.range
}Source§open spec fn drop_ensures(
self,
s0: Self::State,
s1: Self::State,
obl: Self::Obligation,
) -> bool
open spec fn drop_ensures( self, s0: Self::State, s1: Self::State, obl: Self::Obligation, ) -> bool
{ true }Auto Trait Implementations§
impl<M> Freeze for Segment<M>where
M: ?Sized,
impl<M> RefUnwindSafe for Segment<M>where
M: RefUnwindSafe + ?Sized,
impl<M> Send for Segment<M>where
M: ?Sized,
impl<M> Sync for Segment<M>where
M: ?Sized,
impl<M> Unpin for Segment<M>
impl<M> UnsafeUnpin for Segment<M>where
M: ?Sized,
impl<M> UnwindSafe for Segment<M>where
M: UnwindSafe + ?Sized,
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, 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
Source§impl<I> IntoIterator for Iwhere
I: Iterator,
impl<I> IntoIterator for Iwhere
I: Iterator,
§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<VERUS_SPEC__A> IteratorSpec for VERUS_SPEC__A
impl<VERUS_SPEC__A> IteratorSpec for VERUS_SPEC__A
§fn obeys_prophetic_iter_laws(&self) -> bool
fn obeys_prophetic_iter_laws(&self) -> bool
next,
expressed in terms of prophetic spec functions.
Only iterators that terminate (i.e., eventually return None
and then continue to return None) should use this interface.§fn remaining(&self) -> Seq<<VERUS_SPEC__A as Iterator>::Item>
fn remaining(&self) -> Seq<<VERUS_SPEC__A as Iterator>::Item>
§fn will_return_none(&self) -> bool
fn will_return_none(&self) -> bool
None after the above sequence?
(As opposed to hanging indefinitely on a next() call)
Trivially true for most iterators but important for iterators
that apply an exec closure that may not terminate.§fn decrease(&self) -> Option<nat>
fn decrease(&self) -> Option<nat>
§fn initial_value_relation(&self, init: &VERUS_SPEC__A) -> bool
fn initial_value_relation(&self, init: &VERUS_SPEC__A) -> bool
my_vec.iter()). This allows for more ergonomic/intuitive invariants.
When the analysis can infer a spec initial value (by discovering a when_used_as_spec
annotation), the analysis places the value in init.