pub struct VirtPtr {
pub vaddr: Vaddr,
pub range: Ghost<Range<Vaddr>>,
}Expand description
Specification-level virtual pointer with an associated half-open range.
VirtPtr models a C-like pointer used by verification code:
vaddris the current cursor position;rangeis the allocation-like bounds[start, end).
Most operations require is_valid() (i.e., the current pointer is within
range and not one-past-end), while offset operations additionally require
the computed address to stay inside the same range.
Fields§
§vaddr: VaddrCurrent virtual address represented by this pointer value.
range: Ghost<Range<Vaddr>>Logical bounds of the pointer’s valid object/range.
Implementations§
Source§impl VirtPtr
impl VirtPtr
Sourcepub exec fn new(vaddr: Vaddr, len: usize) -> Self
pub exec fn new(vaddr: Vaddr, len: usize) -> Self
({
Self {
vaddr,
range: Ghost(Range {
start: vaddr,
end: (::vstd::prelude::add(vaddr, len)) as usize,
}),
}
}),Creates a pointer at vaddr with logical range [vaddr, vaddr + len).
Sourcepub open spec fn is_defined(self) -> bool
pub open spec fn is_defined(self) -> bool
{ self.range@.start <= self.vaddr <= self.range@.end }Whether the pointer has consistent bounds.
Sourcepub open spec fn is_valid(self) -> bool
pub open spec fn is_valid(self) -> bool
{
&&& self.is_defined()
&&& self.vaddr < self.range@.end
}Whether dereferencing the current pointer position is allowed.
This excludes the one-past-end position (vaddr == range.end).
Sourcepub exec fn read(self, Tracked(mem): Tracked<&MemView>) -> u8
pub exec fn read(self, Tracked(mem): Tracked<&MemView>) -> u8
mem.addr_transl(self.vaddr) is Some,mem
.memory[(mem.addr_transl(self.vaddr)->0).0]
.contents[(mem.addr_transl(self.vaddr)->0).1 as int] is Init,self.is_valid(),returnsmem.read(self.vaddr).value(),Reads one byte from self.vaddr in the provided memory view.
§Verified Properties
§Preconditions
mem.addr_transl(self.vaddr) is Some.- Target byte is initialized:
mem.memory[mem.addr_transl(self.vaddr).unwrap().0].contents[mem.addr_transl(self.vaddr).unwrap().1 as int] is Init. self.is_valid().
§Postconditions
- Returns
mem.read(self.vaddr).value().
Sourcepub exec fn write(self, Tracked(mem): Tracked<&mut MemView>, x: u8)
pub exec fn write(self, Tracked(mem): Tracked<&mut MemView>, x: u8)
old(mem).addr_transl(self.vaddr) is Some,self.is_valid(),ensures*final(mem) == old(mem).write(self.vaddr, x),Writes one byte to self.vaddr in the provided memory view.
§Verified Properties
§Preconditions
old(mem).addr_transl(self.vaddr) is Some.self.is_valid().
§Postconditions
*mem == old(mem).write(self.vaddr, x).
Sourcepub exec fn read_volatile<T: PodOnce>(self, Tracked(mem): Tracked<&MemView>) -> val : T
pub exec fn read_volatile<T: PodOnce>(self, Tracked(mem): Tracked<&MemView>) -> val : T
self.inv(),core::mem::size_of::<T>() <= self.range@.end - self.vaddr,self.vaddr % core::mem::align_of::<T>() == 0,forall |i: usize| {
self.vaddr <= i < self.vaddr + core::mem::size_of::<T>()
==> {
&&& mem.addr_transl(i) is Some
&&& mem.memory.contains_key((mem.addr_transl(i)->0).0)
&&& mem
.memory[(mem.addr_transl(i)->0).0]
.contents[(mem.addr_transl(i)->0).1 as int] is Init
}
},ensurespod_bytes(val) == mem.read_bytes(self.vaddr, core::mem::size_of::<T>()),Reads a PodOnce value using one volatile memory load from a verified memory view.
§Verified Properties
§Preconditions
self.inv().- The readable range
[self.vaddr, self.vaddr + size_of::<T>())must fit inself.range@. self.vaddrmust satisfy the alignment requirement ofT.- Every byte in that range must translate in
memand be initialized.
§Safety
- This function is trusted because the underlying volatile typed read relies on raw-pointer operations that Verus does not yet model directly.
Sourcepub exec fn write_volatile<T: Pod>(
self,
Tracked(mem): Tracked<&mut MemView>,
val: T,
)
pub exec fn write_volatile<T: Pod>( self, Tracked(mem): Tracked<&mut MemView>, val: T, )
self.inv(),core::mem::size_of::<T>() <= self.range@.end - self.vaddr,self.vaddr % core::mem::align_of::<T>() == 0,forall |i: usize| {
self.vaddr <= i < self.vaddr + core::mem::size_of::<T>()
==> {
&&& old(mem).addr_transl(i) is Some
}
},ensures*final(mem) == old(mem).write_bytes(self.vaddr, pod_bytes(val)),final(mem).mappings == old(mem).mappings,old(mem).memory.dom().subset_of(final(mem).memory.dom()),forall |va: usize| old(mem).addr_transl(va) == final(mem).addr_transl(va),Writes a Pod value of size size_of::<T>() bytes using a volatile memory store
to a verified memory view.
For T: PodOnce the underlying store is non-tearing (single instruction). For
arbitrary T: Pod the store may tear across multiple instructions but completes
before this function returns.
§Verified Properties
§Preconditions
self.inv().- The writable range
[self.vaddr, self.vaddr + size_of::<T>())must fit inself.range@. self.vaddrmust satisfy the alignment requirement ofT.- Every byte in that range must translate in
mem.
§Postconditions
- The final memory equals
old(mem).write_bytes(self.vaddr, pod_bytes(val)). mem.mappingsis unchanged (derivable fromwrite_bytes, but stated directly for caller convenience).mem.memory.dom()can only grow (same).addr_translis preserved for every virtual address (same).
§Safety
- This function is trusted because the underlying volatile typed write relies on raw-pointer operations that Verus does not yet model directly.
Sourcepub open spec fn add_spec(self, n: usize) -> Self
pub open spec fn add_spec(self, n: usize) -> Self
{
VirtPtr {
vaddr: (self.vaddr + n) as usize,
range: self.range,
}
}Sourcepub exec fn add(&mut self, n: usize)
pub exec fn add(&mut self, n: usize)
0 <= old(self).vaddr + n < usize::MAX,ensures*final(self) == old(self).add_spec(n),Advances the pointer by n bytes.
This operation only updates the cursor; it does not perform memory access.
§Verified Properties
§Preconditions
0 <= old(self).vaddr + n < usize::MAX.
§Postconditions
*self == old(self).add_spec(n).
Sourcepub open spec fn sub_spec(self, n: usize) -> Self
pub open spec fn sub_spec(self, n: usize) -> Self
{
VirtPtr {
vaddr: (self.vaddr - n) as usize,
range: self.range,
}
}Sourcepub exec fn sub(self, n: usize) -> res : Self
pub exec fn sub(self, n: usize) -> res : Self
n <= self.vaddr,returnsself.sub_spec(n),Returns a new pointer whose address is self.vaddr rewound by n bytes.
Mirrors the shape of [<*const T>::sub] / [<*mut T>::sub] in the raw-pointer
API: takes self by value and returns the new pointer.
§Verified Properties
§Preconditions
n <= self.vaddr(no underflow).
§Postconditions
res == self.sub_spec(n).
Sourcepub open spec fn wrapping_add_spec(self, n: usize) -> Self
pub open spec fn wrapping_add_spec(self, n: usize) -> Self
{
VirtPtr {
vaddr: self.vaddr.wrapping_add(n),
range: self.range,
}
}Sourcepub exec fn wrapping_add(self, n: usize) -> res : Self
pub exec fn wrapping_add(self, n: usize) -> res : Self
self.wrapping_add_spec(n),Returns a new pointer whose address is self.vaddr advanced by n
bytes using wrapping arithmetic.
Sourcepub exec fn cast<T>(self) -> res : *mut T
pub exec fn cast<T>(self) -> res : *mut T
res as usize == self.vaddr,Reinterprets self.vaddr as a typed raw pointer to T.
This is purely a type cast; no memory access is performed and no
alignment is checked. The returned pointer carries no provenance — it
is suitable for runtime checks (e.g., is_aligned) and for unsafe
volatile reads/writes whose preconditions are independently verified.
Sourcepub open spec fn read_offset_spec(self, mem: MemView, n: usize) -> u8
pub open spec fn read_offset_spec(self, mem: MemView, n: usize) -> u8
{ mem.read((self.vaddr + n) as usize).value() }Sourcepub exec fn read_offset(&self, Tracked(mem): Tracked<&MemView>, n: usize) -> u8
pub exec fn read_offset(&self, Tracked(mem): Tracked<&MemView>, n: usize) -> u8
self.vaddr + n < usize::MAX,self.range@.start <= self.vaddr + n < self.range@.end,mem.addr_transl((self.vaddr + n) as usize) is Some,mem
.memory[(mem.addr_transl((self.vaddr + n) as usize)->0).0]
.contents[(mem.addr_transl((self.vaddr + n) as usize)->0).1 as int] is Init,returnsself.read_offset_spec(*mem, n),Reads from self.vaddr + n without mutating self.
Implemented by creating a temporary pointer and calling Self::read.
When self.vaddr == self.range.start, this behaves like array indexing.
§Verified Properties
§Preconditions
self.vaddr + n < usize::MAX.self.range@.start <= self.vaddr + n < self.range@.end.mem.addr_transl((self.vaddr + n) as usize) is Some.- Target byte at offset is initialized.
§Postconditions
- Returns
self.read_offset_spec(*mem, n).
Sourcepub open spec fn write_offset_spec(self, mem: MemView, n: usize, x: u8) -> MemView
pub open spec fn write_offset_spec(self, mem: MemView, n: usize, x: u8) -> MemView
{ mem.write((self.vaddr + n) as usize, x) }Sourcepub exec fn write_offset(
&self,
Tracked(mem): Tracked<&mut MemView>,
n: usize,
x: u8,
)
pub exec fn write_offset( &self, Tracked(mem): Tracked<&mut MemView>, n: usize, x: u8, )
self.inv(),self.vaddr + n < usize::MAX,self.range@.start <= self.vaddr + n < self.range@.end,old(mem).addr_transl((self.vaddr + n) as usize) is Some,ensures*final(mem) == self.write_offset_spec(*old(mem), n, x),Writes to self.vaddr + n without mutating self.
§Verified Properties
§Preconditions
self.inv().self.range@.start <= self.vaddr + n < self.range@.end.old(mem).addr_transl((self.vaddr + n) as usize) is Some.
Sourcepub open spec fn copy_offset_spec(
src: Self,
dst: Self,
mem_src: MemView,
mem_dst: MemView,
n: usize,
) -> MemView
pub open spec fn copy_offset_spec( src: Self, dst: Self, mem_src: MemView, mem_dst: MemView, n: usize, ) -> MemView
{
let x = src.read_offset_spec(mem_src, n);
dst.write_offset_spec(mem_dst, n, x)
}Sourcepub exec fn copy_offset(
src: &Self,
dst: &Self,
Tracked(mem_src): Tracked<&MemView>,
Tracked(mem_dst): Tracked<&mut MemView>,
n: usize,
)
pub exec fn copy_offset( src: &Self, dst: &Self, Tracked(mem_src): Tracked<&MemView>, Tracked(mem_dst): Tracked<&mut MemView>, n: usize, )
src.inv(),dst.inv(),src.vaddr + n < usize::MAX,dst.vaddr + n < usize::MAX,src.range@.start <= src.vaddr + n < src.range@.end,mem_src.addr_transl((src.vaddr + n) as usize) is Some,mem_src.memory.contains_key((mem_src.addr_transl((src.vaddr + n) as usize)->0).0),mem_src
.memory[(mem_src.addr_transl((src.vaddr + n) as usize)->0).0]
.contents[(mem_src.addr_transl((src.vaddr + n) as usize)->0).1 as int] is Init,dst.range@.start <= dst.vaddr + n < dst.range@.end,old(mem_dst).addr_transl((dst.vaddr + n) as usize) is Some,ensures*final(mem_dst) == Self::copy_offset_spec(*src, *dst, *mem_src, *old(mem_dst), n),final(mem_dst).mappings == old(mem_dst).mappings,old(mem_dst).memory.dom().subset_of(final(mem_dst).memory.dom()),Copies one byte from src + n to dst + n.
Source and destination are reasoned about via distinct memory views.
§Verified Properties
§Preconditions
src.inv()anddst.inv().- Source offset and destination offset are both in-range.
- Source offset is mapped and initialized in
mem_src. - Destination offset is mapped in
old(mem_dst).
§Postconditions
*mem_dst == Self::copy_offset_spec(*src, *dst, *mem_src, *old(mem_dst), n).mem_dst.mappings == old(mem_dst).mappings.mem_dst.memory.dom() == old(mem_dst).memory.dom().
Sourcepub open spec fn memcpy_spec(
src: Self,
dst: Self,
mem_src: MemView,
mem_dst: MemView,
n: usize,
) -> MemView
pub open spec fn memcpy_spec( src: Self, dst: Self, mem_src: MemView, mem_dst: MemView, n: usize, ) -> MemView
{
if n == 0 {
mem_dst
} else {
let mem_dst_1 = Self::copy_offset_spec(
src,
dst,
mem_src,
mem_dst,
(n - 1) as usize,
);
Self::memcpy_spec(src, dst, mem_src, mem_dst_1, (n - 1) as usize)
}
}Sourcepub exec fn copy_nonoverlapping(
src: &Self,
dst: &Self,
Tracked(mem_src): Tracked<&MemView>,
Tracked(mem_dst): Tracked<&mut MemView>,
n: usize,
)
pub exec fn copy_nonoverlapping( src: &Self, dst: &Self, Tracked(mem_src): Tracked<&MemView>, Tracked(mem_dst): Tracked<&mut MemView>, n: usize, )
src.inv(),dst.inv(),src.range@.start <= src.vaddr,src.vaddr + n <= src.range@.end,forall |i: usize| {
src.vaddr <= i < src.vaddr + n
==> {
&&& mem_src.addr_transl(i) is Some
&&& mem_src.memory.contains_key((mem_src.addr_transl(i)->0).0)
&&& mem_src
.memory[(mem_src.addr_transl(i)->0).0]
.contents[(mem_src.addr_transl(i)->0).1 as int] is Init
}
},dst.range@.start <= dst.vaddr,dst.vaddr + n <= dst.range@.end,forall |i: usize| {
dst.vaddr <= i < dst.vaddr + n
==> {
&&& old(mem_dst).addr_transl(i) is Some
}
},ensures*final(mem_dst) == Self::memcpy_spec(*src, *dst, *mem_src, *old(mem_dst), n),final(mem_dst).mappings == old(mem_dst).mappings,old(mem_dst).memory.dom().subset_of(final(mem_dst).memory.dom()),forall |i: usize| {
dst.vaddr <= i < dst.vaddr + n
==> {
&&& final(mem_dst).addr_transl(i) is Some
}
},Copies n bytes from src to dst in the given memory view.
mem_src and mem_dst are independent tracked memory views — the verifier
enforces this by virtue of the &MemView / &mut MemView ownership pattern,
so no vaddr-level non-overlap precondition is needed. (mem_src is never
mutated during the copy; each byte is read from its original state.)
§Verified Properties
§Preconditions
src.inv()anddst.inv().- Source slice
[src.vaddr, src.vaddr + n)is in-range and initialized inmem_src. - Destination slice
[dst.vaddr, dst.vaddr + n)is in-range and mapped inold(mem_dst).
§Postconditions
*mem_dst == Self::memcpy_spec(*src, *dst, *mem_src, *old(mem_dst), n).mem_dst.mappings == old(mem_dst).mappings.mem_dst.memory.dom() == old(mem_dst).memory.dom().- Destination slice remains mapped in
mem_dst.
Sourcepub exec fn from_vaddr(vaddr: usize, len: usize) -> r : Self
pub exec fn from_vaddr(vaddr: usize, len: usize) -> r : Self
len <= usize::MAX - vaddr,ensuresr.inv(),r.vaddr == vaddr,r.range@.start == vaddr,r.range@.end == (vaddr + len) as usize,len > 0 ==> r.is_valid(),Builds a valid VirtPtr from a concrete virtual-address range.
§Verified Properties
§Preconditions
len <= usize::MAX - vaddr.
§Postconditions
r.range@.start == vaddr.r.range@.end == (vaddr + len) as usize.- When
len > 0, the result is valid for dereferencing.
Sourcepub exec fn split(self, n: usize) -> r : (Self, Self)
pub exec fn split(self, n: usize) -> r : (Self, Self)
self.is_valid(),0 <= n <= self.range@.end - self.range@.start,self.vaddr == self.range@.start,ensuresr.0.range@.start == self.range@.start,r.0.range@.end == self.range@.start + n,r.0.vaddr == self.range@.start,r.1.range@.start == self.range@.start + n,r.1.range@.end == self.range@.end,r.1.vaddr == self.range@.start + n,Executable helper to split the VirtPtr into two contiguous ranges.
This updates ghost ranges to match a split operation over the same region.
§Verified Properties
§Preconditions
self.is_valid().0 <= n <= self.range@.end - self.range@.start.self.vaddr == self.range@.start.
§Postconditions
- Left pointer covers
[self.range@.start, self.range@.start + n). - Right pointer covers
[self.range@.start + n, self.range@.end).
Trait Implementations§
Auto Trait Implementations§
impl Freeze for VirtPtr
impl RefUnwindSafe for VirtPtr
impl Send for VirtPtr
impl Sync for VirtPtr
impl Unpin for VirtPtr
impl UnsafeUnpin for VirtPtr
impl UnwindSafe for VirtPtr
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
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§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.