Struct abi_stable::sabi_types::RRef
source · pub struct RRef<'a, T> { /* private fields */ }
Expand description
Equivalent to &'a T
,
which allows a few more operations without causing Undefined Behavior.
§Purpose
This type is used as the &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 &T
to &()
to &T
transmutes (when T
isn’t zero-sized),
it required defining RRef
to allow a reference-like type that can be transmuted.
§Example
This example demonstrates how a simple &dyn Any
-like type can be implemented.
use abi_stable::{marker_type::ErasedObject, std_types::UTypeId, RRef};
fn main() {
let value = WithTypeId::new(5u32);
let erased = value.erase();
assert_eq!(WithTypeId::downcast::<i32>(erased), None);
assert_eq!(WithTypeId::downcast::<bool>(erased), None);
assert_eq!(WithTypeId::downcast::<u32>(erased), Some(&value));
}
// `#[repr(C))]` with a trailing `T` field is required for soundly transmuting from
// `RRef<'a, WithTypeId<T>>` to `RRef<'a, WithTypeId<ErasedObject>>`.
#[repr(C)]
#[derive(Debug, PartialEq)]
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(&self) -> RRef<'_, WithTypeId<ErasedObject>> {
unsafe { RRef::new(self).transmute::<WithTypeId<ErasedObject>>() }
}
}
impl WithTypeId<ErasedObject> {
pub fn downcast<T>(this: RRef<'_, Self>) -> Option<&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_ref::<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> RRef<'a, T>
impl<'a, T> RRef<'a, T>
sourcepub const fn new(ref_: &'a T) -> Self
pub const fn new(ref_: &'a T) -> Self
Constructs this RRef from a reference.
§Example
use abi_stable::sabi_types::RRef;
struct GetPtr<'a, T>(&'a T);
impl<'a, T: 'a> GetPtr<'a, T> {
const REF: &'a Option<T> = &None;
const STATIC: RRef<'a, Option<T>> = RRef::new(Self::REF);
}
sourcepub const unsafe fn from_raw(ref_: *const T) -> Selfwhere
T: 'a,
pub const unsafe fn from_raw(ref_: *const T) -> Selfwhere
T: 'a,
Constructs this RRef from a raw pointer.
§Safety
You must ensure that the raw pointer is valid for the 'a
lifetime,
and points to a fully initialized and aligned T
.
§Example
use abi_stable::sabi_types::RRef;
struct GetPtr<'a, T>(&'a T);
impl<'a, T: 'a> GetPtr<'a, T> {
const PTR: *const Option<T> = &None;
const STATIC: RRef<'a, Option<T>> = unsafe { RRef::from_raw(Self::PTR) };
}
sourcepub const fn get(self) -> &'a T
pub const fn get(self) -> &'a T
Casts this to an equivalent reference.
§Example
use abi_stable::RRef;
let rref = RRef::new(&89);
assert_eq!(rref.get(), &89);
sourcepub const fn get_copy(self) -> Twhere
T: Copy,
pub const fn get_copy(self) -> Twhere
T: Copy,
Copies the value that this points to.
§Example
use abi_stable::RRef;
let rref = RRef::new(&55);
assert_eq!(rref.get_copy(), 55);
sourcepub const fn as_ptr(self) -> *const T
pub const fn as_ptr(self) -> *const T
Casts this to an equivalent raw pointer.
§Example
use abi_stable::RRef;
let rref = RRef::new(&89);
unsafe {
assert_eq!(*rref.as_ptr(), 89);
}
sourcepub const unsafe fn transmute<U>(self) -> RRef<'a, U>where
U: 'a,
pub const unsafe fn transmute<U>(self) -> RRef<'a, U>where
U: 'a,
Transmutes this RRef<'a,T>
to a RRef<'a,U>
.
§Safety
Either of these must be the case:
-
RRef<'a, U>
was the original type of thisRRef<'a, T>
.
§Example
use abi_stable::RRef;
use std::num::Wrapping;
let rref = RRef::new(&13u32);
// safety: Wrapping is a `#[repr(transparent)]` wrapper with one `pub` field.
let trans = unsafe { rref.transmute::<Wrapping<u32>>() };
assert_eq!(trans, RRef::new(&Wrapping(13u32)));
sourcepub const fn transmute_into_raw<U>(self) -> *const U
pub const fn transmute_into_raw<U>(self) -> *const U
Transmutes this to a raw pointer pointing to a different type.
sourcepub const unsafe fn transmute_into_ref<U>(self) -> &'a Uwhere
U: 'a,
pub const unsafe fn transmute_into_ref<U>(self) -> &'a Uwhere
U: 'a,
Transmutes this to a reference pointing to a different type.
§Safety
Either of these must be the case:
-
RRef<'a, U>
was the original type of thisRRef<'a, T>
.
§Example
use abi_stable::{std_types::Tuple2, RRef};
unsafe {
let reff = RRef::new(&Tuple2(3u32, 5u64));
assert_eq!(reff.transmute_into_ref::<u32>(), &3u32);
}
Trait Implementations§
source§impl<'a, T, U> CanTransmuteElement<U> for RRef<'a, T>where
U: 'a,
impl<'a, T, U> CanTransmuteElement<U> for RRef<'a, T>where
U: 'a,
source§type TransmutedPtr = RRef<'a, U>
type TransmutedPtr = RRef<'a, U>
source§unsafe fn transmute_element_(self) -> Self::TransmutedPtr
unsafe fn transmute_element_(self) -> Self::TransmutedPtr
source§impl<'a, T> GetPointerKind for RRef<'a, T>
impl<'a, T> GetPointerKind for RRef<'a, T>
source§impl<'a, T> GetStaticEquivalent_ for RRef<'a, T>where
T: __StableAbi + 'a,
impl<'a, T> GetStaticEquivalent_ for RRef<'a, T>where
T: __StableAbi + 'a,
source§type StaticEquivalent = _static_RRef<'static, <T as GetStaticEquivalent_>::StaticEquivalent>
type StaticEquivalent = _static_RRef<'static, <T as GetStaticEquivalent_>::StaticEquivalent>
'static
equivalent of Self
source§impl<'a, T> Ord for RRef<'a, T>where
T: Ord,
impl<'a, T> Ord for RRef<'a, T>where
T: Ord,
source§impl<'a, T> PartialOrd for RRef<'a, T>where
T: PartialOrd,
impl<'a, T> PartialOrd for RRef<'a, T>where
T: PartialOrd,
source§impl<'a, T> StableAbi for RRef<'a, T>where
T: __StableAbi + 'a,
impl<'a, T> StableAbi for RRef<'a, T>where
T: __StableAbi + 'a,
source§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> Copy for RRef<'a, T>
impl<'a, T> Eq for RRef<'a, T>where
T: Eq,
impl<'a, T> Send for RRef<'a, T>
impl<'a, T> Sync for RRef<'a, T>
Auto Trait Implementations§
impl<'a, T> Freeze for RRef<'a, T>
impl<'a, T> RefUnwindSafe for RRef<'a, T>where
T: RefUnwindSafe,
impl<'a, T> Unpin for RRef<'a, T>
impl<'a, T> UnwindSafe for RRef<'a, T>where
T: RefUnwindSafe,
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
source§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
source§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
source§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
source§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
source§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
source§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
source§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
source§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
source§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<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)source§impl<T> ImmutableRef for T
impl<T> ImmutableRef for T
source§impl<'a, T> RCowCompatibleRef<'a> for Twhere
T: Clone + 'a,
impl<'a, T> RCowCompatibleRef<'a> for Twhere
T: Clone + 'a,
source§fn as_c_ref(from: &'a T) -> <T as RCowCompatibleRef<'a>>::RefC
fn as_c_ref(from: &'a T) -> <T as RCowCompatibleRef<'a>>::RefC
source§fn as_rust_ref(from: <T as RCowCompatibleRef<'a>>::RefC) -> &'a T
fn as_rust_ref(from: <T as RCowCompatibleRef<'a>>::RefC) -> &'a 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) -> Uwhere
F: FnOnce(&'a Self) -> U,
fn piped_ref<'a, F, U>(&'a self, f: F) -> Uwhere
F: FnOnce(&'a Self) -> 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