Struct abi_stable::sabi_types::RMut
source · pub struct RMut<'a, T> { /* private fields */ }
Expand description
Equivalent to &'a mut T
,
which allows a few more operations without causing Undefined Behavior.
Purpose
This type is used as the &mut self
parameter in abi_stable trait objects
because it can be soundly transmuted
to point to other smaller but compatible types, then back to the original type.
This crate is tested with miri to detect bugs in unsafe code,
which implements the Stacked Borrows model.
Because that model forbids &mut T
to &mut ()
to &mut T
transmutes
(when T
isn’t zero-sized),
it required defining RMut
to allow a mutable-reference-like type that can be transmuted.
Example
This example demonstrates how a simple &mut dyn Any
-like type can be implemented.
use abi_stable::{marker_type::ErasedObject, std_types::UTypeId, RMut};
fn main() {
let mut value = WithTypeId::new(5u32);
let mut clone = value.clone();
let mut erased = value.erase();
assert_eq!(WithTypeId::downcast::<i32>(erased.reborrow()), None);
assert_eq!(WithTypeId::downcast::<bool>(erased.reborrow()), None);
assert_eq!(
WithTypeId::downcast::<u32>(erased.reborrow()),
Some(&mut clone)
);
}
// `#[repr(C))]` with a trailing `T` field is required for soundly transmuting from
// `RMut<'a, WithTypeId<T>>` to `RMut<'a, WithTypeId<ErasedObject>>`.
#[repr(C)]
#[derive(Debug, PartialEq, Clone)]
struct WithTypeId<T> {
type_id: UTypeId,
value: T,
}
impl<T> WithTypeId<T> {
pub fn new(value: T) -> Self
where
T: 'static,
{
Self {
type_id: UTypeId::new::<T>(),
value,
}
}
pub fn erase(&mut self) -> RMut<'_, WithTypeId<ErasedObject>> {
unsafe { RMut::new(self).transmute::<WithTypeId<ErasedObject>>() }
}
}
impl WithTypeId<ErasedObject> {
pub fn downcast<T>(this: RMut<'_, Self>) -> Option<&mut WithTypeId<T>>
where
T: 'static,
{
if this.get().type_id == UTypeId::new::<T>() {
// safety: we checked that type parameter was `T`
unsafe { Some(this.transmute_into_mut::<WithTypeId<T>>()) }
} else {
None
}
}
}
Type Prefix
A type parameter U
is considered a prefix of T
in all of these cases:
-
U
is a zero-sized type with an alignment equal or lower thanT
-
U
is a#[repr(transparent)]
wrapper overT
-
U
andT
are both#[repr(C)]
structs, in whichT
starts with the fields ofU
in the same order, andU
has an alignment equal to or lower thanT
.
Please note that it can be unsound to transmute a non-local type if it has private fields, since it may assume it was constructed in a particular way.
Implementations§
source§impl<'a, T> RMut<'a, T>
impl<'a, T> RMut<'a, T>
sourcepub fn new(ref_: &'a mut T) -> Self
pub fn new(ref_: &'a mut T) -> Self
Constructs this RMut from a mutable reference
Example
use abi_stable::RMut;
let mut foo = 3;
let mut rmut = RMut::new(&mut foo);
*rmut.get_mut() += 10;
assert_eq!(*rmut.get(), 13);
assert_eq!(foo, 13);
sourcepub const unsafe fn from_raw(ref_: *mut T) -> Selfwhere
T: 'a,
pub const unsafe fn from_raw(ref_: *mut T) -> Selfwhere
T: 'a,
Constructs this RMut from a raw pointer.
Safety
You must ensure that the raw pointer is valid for the 'a
lifetime,
points to a fully initialized and aligned T
,
and that this is the only active pointer to that value.
Example
use abi_stable::RMut;
let mut foo = 3u32;
// safety:
// `&mut foo` is casted to a pointer to a compatible type (`u32` to `i32`),
// `rmut` is only used for the lifetime of foo,
// and is the only active pointer to `foo` while it's used.
let mut rmut = unsafe { RMut::from_raw((&mut foo) as *mut u32 as *mut i32) };
*rmut.get_mut() -= 4;
assert_eq!(*rmut.get(), -1);
assert_eq!(foo, !0);
sourcepub fn reborrow(&mut self) -> RMut<'_, T>
pub fn reborrow(&mut self) -> RMut<'_, T>
Reborrows this RMut
, with a shorter lifetime.
This allows passing an RMut
to functions multiple times,
but with a shorter lifetime argument.
Example
use abi_stable::RMut;
let mut foo = 3;
let mut rmut = RMut::new(&mut foo);
assert_eq!(mutate(rmut.reborrow()), 6);
assert_eq!(mutate(rmut.reborrow()), 12);
assert_eq!(mutate(rmut.reborrow()), 24);
// last use of rmut, so it can be moved instead of being reborrowed.
assert_eq!(mutate(rmut), 48);
fn mutate(mut rmut: RMut<'_, u32>) -> u32 {
*rmut.get_mut() *= 2;
rmut.get_copy()
}
sourcepub const fn get(&self) -> &T
pub const fn get(&self) -> &T
Reborrows this RMut
into a shared reference.
Note that because the reference reborrows this RMut<'a, T>
its lifetime argument is strictly smaller.
To turn an RMut<'a, T>
into a &'a T
(with the same lifetime argument)
you can use into_ref
.
Example
use abi_stable::RMut;
let mut val = 89;
let rmut = RMut::new(&mut val);
assert_eq!(rmut.get(), &89);
Lifetimes
This demonstrates when into_ref
works, but get
doesn’t.
fn stuff<'a>(x: RMut<'a, i32>) -> &'a i32 {
x.into_ref()
}
This doesn’t compile, because get
reborrows foo
.
fn stuff<'a>(foo: RMut<'a, i32>) -> &'a i32 {
foo.get()
}
sourcepub const fn get_copy(&self) -> Twhere
T: Copy,
pub const fn get_copy(&self) -> Twhere
T: Copy,
Copies the value that this RMut
points to.
Example
use abi_stable::RMut;
let mut val = "hello";
let mut rmut = RMut::new(&mut val);
*rmut.get_mut() = "world";
assert_eq!(rmut.get_copy(), "world");
sourcepub const fn into_ref(self) -> &'a T
pub const fn into_ref(self) -> &'a T
Converts this RMut<'a, T>
into a &'a T
Example
use abi_stable::RMut;
let mut val = 89;
assert_eq!(mutate(RMut::new(&mut val)), &44);
fn mutate(mut rmut: RMut<'_, u32>) -> &u32 {
*rmut.get_mut() /= 2;
rmut.into_ref()
}
sourcepub fn get_mut(&mut self) -> &mut T
pub fn get_mut(&mut self) -> &mut T
Reborrows this RMut
into a mutable reference.
Note that because the mutable reference reborrows this RMut<'a, T>
its lifetime argument is strictly smaller.
To turn an RMut<'a, T>
into a &'a mut T
(with the same lifetime argument)
you can use into_mut
.
Example
use abi_stable::RMut;
let mut val = 89;
let mut rmut = RMut::new(&mut val);
assert_eq!(rmut.get_mut(), &mut 89);
*rmut.get_mut() += 10;
assert_eq!(rmut.get_mut(), &mut 99);
Lifetimes
This demonstrates when into_mut
works, but get_mut
doesn’t.
fn stuff<'a>(x: RMut<'a, i32>) -> &'a mut i32 {
x.into_mut()
}
This doesn’t compile, because get_mut
reborrows foo
.
fn stuff<'a>(mut foo: RMut<'a, i32>) -> &'a mut i32 {
foo.get_mut()
}
sourcepub fn into_mut(self) -> &'a mut T
pub fn into_mut(self) -> &'a mut T
Converts this RMut<'a, T>
into a &'a mut T
Example
use abi_stable::RMut;
let mut val = 13;
let rmut = RMut::new(&mut val);
assert_eq!(rmut.get(), &13);
*rmut.into_mut() += 8;
assert_eq!(val, 21);
sourcepub const fn as_ptr(&self) -> *const T
pub const fn as_ptr(&self) -> *const T
Reborrows this RMut
as a const raw pointer.
Example
use abi_stable::RMut;
let mut val = 34;
let rmut = RMut::new(&mut val);
unsafe {
assert_eq!(*rmut.as_ptr(), 34);
}
sourcepub fn as_mut_ptr(&mut self) -> *mut T
pub fn as_mut_ptr(&mut self) -> *mut T
Reborrows this RMut
as a mutable raw pointer.
Example
use abi_stable::RMut;
let mut val = 34;
let mut rmut = RMut::new(&mut val);
unsafe {
rmut.as_mut_ptr().write(7);
*rmut.as_mut_ptr() *= 2;
assert_eq!(val, 14);
}
sourcepub const fn into_raw(self) -> *mut T
pub const fn into_raw(self) -> *mut T
Converts this RMut<'a, T>
into a *mut T
Example
use abi_stable::RMut;
let mut val = 89;
let rmut = RMut::new(&mut val);
unsafe {
let ptr = rmut.into_raw();
ptr.write(27);
*ptr += 2;
assert_eq!(val, 29);
}
sourcepub const fn transmute_into_raw<U>(self) -> *mut U
pub const fn transmute_into_raw<U>(self) -> *mut U
Transmutes this RMut<'a, T>
to a *mut U
.
Example
use abi_stable::RMut;
let mut val = Direction::Up;
let rmut = RMut::new(&mut val);
assert_eq!(rmut.get(), &Direction::Up);
let ptr = rmut.transmute_into_raw::<u8>();
unsafe {
assert_eq!(*ptr, 2);
*ptr = 3;
}
assert_eq!(val, Direction::Down);
#[repr(u8)]
#[derive(Debug, PartialEq)]
enum Direction {
Left = 0,
Right = 1,
Up = 2,
Down = 3,
}
sourcepub unsafe fn transmute_into_mut<U>(self) -> &'a mut Uwhere
U: 'a,
pub unsafe fn transmute_into_mut<U>(self) -> &'a mut Uwhere
U: 'a,
Transmutes this RMut<'a, T>
to a &'a mut U
.
Safety
Either of these must be the case:
-
RMut<'a, U>
was the original type of thisRMut<'a, T>
.
Example
use abi_stable::RMut;
let mut val = 13u8;
let rmut = RMut::new(&mut val);
assert_eq!(rmut.get(), &13);
unsafe {
*rmut.transmute_into_mut::<i8>() = -1;
}
assert_eq!(val, 255);
sourcepub const unsafe fn transmute<U>(self) -> RMut<'a, U>where
U: 'a,
pub const unsafe fn transmute<U>(self) -> RMut<'a, U>where
U: 'a,
Transmutes this RMut<'a, T>
to a RMut<'a,U>
.
Safety
Either of these must be the case:
-
RMut<'a, U>
was the original type of thisRMut<'a, T>
.
Example
use abi_stable::RMut;
let mut val: [u32; 3] = [2, 3, 0];
let mut rmut = RMut::new(&mut val);
unsafe {
// safety:
// it's sound to transmute mutable references of arrays into shorter arrays.
//
// The `.reborrow()` prevents the `rmut` from being consumed.
compute_next(rmut.reborrow().transmute::<[u32; 2]>());
assert_eq!(rmut.get_copy(), [3, 5, 0]);
compute_next(rmut.reborrow().transmute::<[u32; 2]>());
assert_eq!(rmut.get_copy(), [5, 8, 0]);
// last use of `rmut`, so no need to reborrow
compute_next(rmut.transmute::<[u32; 2]>());
}
assert_eq!(val, [8, 13, 0]);
fn compute_next(rmut: RMut<'_, [u32; 2]>) {
let [v0, v1] = rmut.into_mut();
let next = *v0 + *v1;
*v0 = std::mem::replace(v1, next);
}
sourcepub const fn as_rref<'r>(&'r self) -> RRef<'r, T>
pub const fn as_rref<'r>(&'r self) -> RRef<'r, T>
Reborrows this RMut<'a, T>
into an RRef<'_, T>
Example
use abi_stable::{RMut, RRef};
let mut val = 77;
let rmut = RMut::new(&mut val);
for _ in 0..10 {
assertion(rmut.as_rref());
}
fn assertion(rref: RRef<'_, u32>) {
assert_eq!(rref.get_copy(), 77);
}
Trait Implementations§
source§impl<'a, T, U> CanTransmuteElement<U> for RMut<'a, T>where
U: 'a,
impl<'a, T, U> CanTransmuteElement<U> for RMut<'a, T>where
U: 'a,
§type TransmutedPtr = RMut<'a, U>
type TransmutedPtr = RMut<'a, U>
source§unsafe fn transmute_element_(self) -> Self::TransmutedPtr
unsafe fn transmute_element_(self) -> Self::TransmutedPtr
source§impl<'a, T> GetPointerKind for RMut<'a, T>
impl<'a, T> GetPointerKind for RMut<'a, T>
source§impl<'a, T> GetStaticEquivalent_ for RMut<'a, T>where
T: __StableAbi + 'a,
impl<'a, T> GetStaticEquivalent_ for RMut<'a, T>where
T: __StableAbi + 'a,
§type StaticEquivalent = _static_RMut<'static, <T as GetStaticEquivalent_>::StaticEquivalent>
type StaticEquivalent = _static_RMut<'static, <T as GetStaticEquivalent_>::StaticEquivalent>
'static
equivalent of Self
source§impl<'a, T> Ord for RMut<'a, T>where
T: Ord,
impl<'a, T> Ord for RMut<'a, T>where
T: Ord,
source§impl<'a, T> PartialEq for RMut<'a, T>where
T: PartialEq,
impl<'a, T> PartialEq for RMut<'a, T>where
T: PartialEq,
source§impl<'a, T> PartialOrd for RMut<'a, T>where
T: PartialOrd,
impl<'a, T> PartialOrd for RMut<'a, T>where
T: PartialOrd,
1.0.0 · source§fn le(&self, other: &Rhs) -> bool
fn le(&self, other: &Rhs) -> bool
self
and other
) and is used by the <=
operator. Read moresource§impl<'a, T> StableAbi for RMut<'a, T>where
T: __StableAbi + 'a,
impl<'a, T> StableAbi for RMut<'a, T>where
T: __StableAbi + 'a,
§type IsNonZeroType = <NonNull<T> as StableAbi>::IsNonZeroType
type IsNonZeroType = <NonNull<T> as StableAbi>::IsNonZeroType
source§const LAYOUT: &'static TypeLayout = _
const LAYOUT: &'static TypeLayout = _
source§const ABI_CONSTS: AbiConsts = _
const ABI_CONSTS: AbiConsts = _
const
-equivalents of the associated types.impl<'a, T> Eq for RMut<'a, T>where
T: Eq,
impl<'a, T> Send for RMut<'a, T>
impl<'a, T> Sync for RMut<'a, T>
Auto Trait Implementations§
impl<'a, T> RefUnwindSafe for RMut<'a, T>where
T: RefUnwindSafe,
impl<'a, T> Unpin for RMut<'a, T>
impl<'a, T> !UnwindSafe for RMut<'a, T>
Blanket Implementations§
source§impl<T> AlignerFor<1> for T
impl<T> AlignerFor<1> for T
source§impl<T> AlignerFor<1024> for T
impl<T> AlignerFor<1024> for T
§type Aligner = AlignTo1024<T>
type Aligner = AlignTo1024<T>
AlignTo*
type which aligns Self
to ALIGNMENT
.source§impl<T> AlignerFor<128> for T
impl<T> AlignerFor<128> for T
§type Aligner = AlignTo128<T>
type Aligner = AlignTo128<T>
AlignTo*
type which aligns Self
to ALIGNMENT
.source§impl<T> AlignerFor<16> for T
impl<T> AlignerFor<16> for T
source§impl<T> AlignerFor<16384> for T
impl<T> AlignerFor<16384> for T
§type Aligner = AlignTo16384<T>
type Aligner = AlignTo16384<T>
AlignTo*
type which aligns Self
to ALIGNMENT
.source§impl<T> AlignerFor<2> for T
impl<T> AlignerFor<2> for T
source§impl<T> AlignerFor<2048> for T
impl<T> AlignerFor<2048> for T
§type Aligner = AlignTo2048<T>
type Aligner = AlignTo2048<T>
AlignTo*
type which aligns Self
to ALIGNMENT
.source§impl<T> AlignerFor<256> for T
impl<T> AlignerFor<256> for T
§type Aligner = AlignTo256<T>
type Aligner = AlignTo256<T>
AlignTo*
type which aligns Self
to ALIGNMENT
.source§impl<T> AlignerFor<32> for T
impl<T> AlignerFor<32> for T
source§impl<T> AlignerFor<32768> for T
impl<T> AlignerFor<32768> for T
§type Aligner = AlignTo32768<T>
type Aligner = AlignTo32768<T>
AlignTo*
type which aligns Self
to ALIGNMENT
.source§impl<T> AlignerFor<4> for T
impl<T> AlignerFor<4> for T
source§impl<T> AlignerFor<4096> for T
impl<T> AlignerFor<4096> for T
§type Aligner = AlignTo4096<T>
type Aligner = AlignTo4096<T>
AlignTo*
type which aligns Self
to ALIGNMENT
.source§impl<T> AlignerFor<512> for T
impl<T> AlignerFor<512> for T
§type Aligner = AlignTo512<T>
type Aligner = AlignTo512<T>
AlignTo*
type which aligns Self
to ALIGNMENT
.source§impl<T> AlignerFor<64> for T
impl<T> AlignerFor<64> for T
source§impl<T> AlignerFor<8> for T
impl<T> AlignerFor<8> for T
source§impl<T> AlignerFor<8192> for T
impl<T> AlignerFor<8192> for T
§type Aligner = AlignTo8192<T>
type Aligner = AlignTo8192<T>
AlignTo*
type which aligns Self
to ALIGNMENT
.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<S> ROExtAcc for S
impl<S> ROExtAcc for S
source§fn f_get<F>(&self, offset: FieldOffset<S, F, Aligned>) -> &F
fn f_get<F>(&self, offset: FieldOffset<S, F, Aligned>) -> &F
offset
. Read moresource§fn f_get_mut<F>(&mut self, offset: FieldOffset<S, F, Aligned>) -> &mut F
fn f_get_mut<F>(&mut self, offset: FieldOffset<S, F, Aligned>) -> &mut F
offset
. Read moresource§fn f_get_ptr<F, A>(&self, offset: FieldOffset<S, F, A>) -> *const F
fn f_get_ptr<F, A>(&self, offset: FieldOffset<S, F, A>) -> *const F
offset
. Read moresource§fn f_get_mut_ptr<F, A>(&mut self, offset: FieldOffset<S, F, A>) -> *mut F
fn f_get_mut_ptr<F, A>(&mut self, offset: FieldOffset<S, F, A>) -> *mut F
offset
. Read moresource§impl<S> ROExtOps<Aligned> for S
impl<S> ROExtOps<Aligned> for S
source§fn f_replace<F>(&mut self, offset: FieldOffset<S, F, Aligned>, value: F) -> F
fn f_replace<F>(&mut self, offset: FieldOffset<S, F, Aligned>, value: F) -> F
offset
) with value
,
returning the previous value of the field. Read moresource§fn f_get_copy<F>(&self, offset: FieldOffset<S, F, Aligned>) -> Fwhere
F: Copy,
fn f_get_copy<F>(&self, offset: FieldOffset<S, F, Aligned>) -> Fwhere
F: Copy,
source§impl<S> ROExtOps<Unaligned> for S
impl<S> ROExtOps<Unaligned> for S
source§fn f_replace<F>(&mut self, offset: FieldOffset<S, F, Unaligned>, value: F) -> F
fn f_replace<F>(&mut self, offset: FieldOffset<S, F, Unaligned>, value: F) -> F
offset
) with value
,
returning the previous value of the field. Read moresource§fn f_get_copy<F>(&self, offset: FieldOffset<S, F, Unaligned>) -> Fwhere
F: Copy,
fn f_get_copy<F>(&self, offset: FieldOffset<S, F, Unaligned>) -> Fwhere
F: Copy,
source§impl<T> SelfOps for Twhere
T: ?Sized,
impl<T> SelfOps for Twhere
T: ?Sized,
source§fn piped<F, U>(self, f: F) -> U
fn piped<F, U>(self, f: F) -> U
source§fn piped_ref<'a, F, U>(&'a self, f: F) -> U
fn piped_ref<'a, F, U>(&'a self, f: F) -> U
piped
except that the function takes &Self
Useful for functions that take &Self
instead of Self
. Read moresource§fn piped_mut<'a, F, U>(&'a mut self, f: F) -> Uwhere
F: FnOnce(&'a mut Self) -> U,
fn piped_mut<'a, F, U>(&'a mut self, f: F) -> Uwhere
F: FnOnce(&'a mut Self) -> U,
piped
, except that the function takes &mut Self
.
Useful for functions that take &mut Self
instead of Self
.source§fn mutated<F>(self, f: F) -> Self
fn mutated<F>(self, f: F) -> Self
source§fn observe<F>(self, f: F) -> Self
fn observe<F>(self, f: F) -> Self
source§fn as_ref_<T>(&self) -> &T
fn as_ref_<T>(&self) -> &T
AsRef
,
using the turbofish .as_ref_::<_>()
syntax. Read more