Struct Erased

Source
pub struct Erased<T> { /* private fields */ }
Expand description

The Erased struct witnesses the logical ownership of a value of type T while remaining zero-sized. This can be used for ghost proofs of soundness.

Erased should be thought of a zero-sized owner of T. It is useful for inclusion in data structures where the value might not be eliminated by the compiler. It likely is not necessary for short-lived data.

NOTE: drop implementations will never be called, as Exists guarantees the existence of a valid T, which might not be true if they were called. On the other hand, since it does not hold a T, it cannot drop T when it is itself dropped

Secondly, keep in mind that while Erased serves as evidence, it does not include sufficient provenance for Stacked Borrows or LLVM, and so it is not techinically sound to recover a reference &T from an Exists<&T> and *mut T or &UnsafeCell<T> even when T is Singleton, but this could be possible if T is zero-sized. Because of the missing provenance, creating a reference this way could invalidate the original reference on which this Exists instance was based.

Implementations§

Source§

impl<T> Erased<T>

Source

pub const fn new(t: T) -> Self

Source

pub const unsafe fn new_unchecked() -> Self

This function constructs a value of Erased without taking logical ownership of a T.

§Safety

Constructing this asserts that there is a value of type T which has been leaked, or in which it is guaranteed that the program behaves the same up to observation as if a zero-sized copy of T were being passed.

Source

pub fn borrow(&self) -> Erased<&T>

Turns a &Erased into an Erased<&T>

This can be especially useful when storing the Erased inside another wrapper type

use core::cell::RefCell;
struct Token;
let lock = RefCell::new(Erased::new(Token));

let locked = lock.borrow();
let _: Erased<&Token> = locked.borrow();
Source

pub fn borrow_mut(&mut self) -> Erased<&mut T>

Turns a &mut Erased into an Erased<&mut T>

This can be especially useful when storing the Erased inside another wrapper type

use core::cell::RefCell;
struct Token;
let lock = RefCell::new(Erased::new(Token));

let mut locked = lock.borrow_mut();
let _: Erased<&mut Token> = locked.borrow_mut();
Source

pub unsafe fn map<R, F: FnOnce(T) -> R>(self, _: impl Exists<F>) -> Erased<R>

Maps a function on the inside of the Erased field.

§Safety

Due to the strictness guarantees, the passed closure must not cause any visible side effects, including side effects caused by owning R

Source

pub unsafe fn map_borrow<'a, R, F: FnOnce(&'a T) -> R>( &'a self, _: impl Exists<F>, ) -> Erased<R>

Maps a function on the borrow of the Erased field.

§Safety

Due to the strictness guarantees, the passed closure must not cause any visible side effects, including side effects caused by owning R

Source

pub unsafe fn map_borrow_mut<'a, R, F: FnOnce(&'a mut T) -> R>( &'a mut self, _: impl Exists<F>, ) -> Erased<R>

Maps a function on the mutable borrow of the Erased field.

§Safety

Due to the strictness guarantees, the passed closure must not cause any visible side effects, including side effects caused by owning R

Source

pub fn exists(self) -> impl Exists<T>

Fallback function which converts this Erased value into an Exists implementer.

This exists because we cannot allow general trait implementations due to coherence rules, but we can’t be sufficiently flexible in trait implementations due to a lack of subtyping constraints or trait covariance, which would mean references would be too inflexible

Source§

impl<T> Erased<Erased<T>>

Source

pub fn flatten(self) -> Erased<T>

An erased erased value can be flattened into a single erasure, since Erased is notionally equivalent to T

Source§

impl<'a, T> Erased<&'a mut T>

Source

pub fn reborrow<'b>(&'b mut self) -> Erased<&'b mut T>

Re-borrow this erased mutable borrow. Usually this is implicit in Rust, but not for general wrappers. This can be seen as a “clone” method for mutable borrows, as it allows you to retain the erased borrow after the end of the lifetime.

The Exists trait can perform this conversion automatically.

struct Token;
fn recursively(mut b: Erased<&mut Token>) {
 recursively(b.reborrow());
 recursively(b);
}
Source

pub fn read<'b>(&'b self) -> Erased<&'b T>

Borrow this erased mutable borrow as immutable. This is effectively a Deref method under Erased

The Exists trait can perform this conversion automatically.

struct Lock;
fn use_lock(write: Erased<&mut Lock>) {
  read_from(write.read());
}

fn read_from(read: Erased<&Lock>) { }
Source

pub fn into_shared(self) -> Erased<&'a T>

Consume this erased mutable borrow to turn it into an immutable borrow.

The Exists trait can perform this conversion automatically.

See also read, which is often more useful. This method uses the full inner lifetime without needing to borrow.

struct Lock;
struct MutWrapper<'a> (Erased<&'a mut Lock>);
struct Wrapper<'a> (Erased<&'a Lock>);
impl<'a> MutWrapper<'a> {
  pub fn into_read(self) -> Wrapper<'a> {
     Wrapper(self.0.into_shared())
  }
}

Trait Implementations§

Source§

impl<T: Copy> Clone for Erased<T>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<'a, 'b, T> Exists<&'a T> for &'a Erased<&'b T>

Source§

impl<'a, 'b: 'a, T> Exists<&'a T> for &'a Erased<&'b mut T>

Source§

impl<'a, 'b: 'a, T> Exists<&'a T> for Erased<&'b T>

Source§

impl<'a, 'b: 'a, T> Exists<&'a T> for Erased<&'b mut T>

Source§

impl<'a, 'b: 'a, T> Exists<&'a mut T> for &'a mut Erased<&'b mut T>

Source§

impl<'a, 'b: 'a, T> Exists<&'a mut T> for Erased<&'b mut T>

Source§

impl<T> From<T> for Erased<T>

Source§

fn from(t: T) -> Self

Converts to this type from the input type.
Source§

impl<T: Copy> Copy for Erased<T>

Source§

impl<'a, T: SingleThread> SingleThread for Erased<T>

Source§

impl<'a, T: Singleton> Singleton for Erased<T>

Auto Trait Implementations§

§

impl<T> Freeze for Erased<T>

§

impl<T> RefUnwindSafe for Erased<T>
where T: RefUnwindSafe,

§

impl<T> Send for Erased<T>
where T: Send,

§

impl<T> Sync for Erased<T>
where T: Sync,

§

impl<T> Unpin for Erased<T>
where T: Unpin,

§

impl<T> UnwindSafe for Erased<T>
where T: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Exists<T> for T

Source§

fn erase(self) -> Erased<T>

Source§

impl<T> From<!> for T

Source§

fn from(t: !) -> T

Converts to this type from the input type.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.