[][src]Module rustc_data_structures::owning_ref

⚙️ This is an internal compiler API. (rustc_private)

This crate is being loaded from the sysroot, a permanently unstable location for private compiler dependencies. It is not intended for general use. Prefer using a public version of this crate from crates.io via Cargo.toml.

An owning reference.

This crate provides the owning reference types OwningRef and OwningRefMut that enables it to bundle a reference together with the owner of the data it points to. This allows moving and dropping of a OwningRef without needing to recreate the reference.

This can sometimes be useful because Rust borrowing rules normally prevent moving a type that has been moved from. For example, this kind of code gets rejected:

This example deliberately fails to compile
fn return_owned_and_referenced<'a>() -> (Vec<u8>, &'a [u8]) {
    let v = vec![1, 2, 3, 4];
    let s = &v[1..3];
    (v, s)
}

Even though, from a memory-layout point of view, this can be entirely safe if the new location of the vector still lives longer than the lifetime 'a of the reference because the backing allocation of the vector does not change.

This library enables this safe usage by keeping the owner and the reference bundled together in a wrapper type that ensure that lifetime constraint:

fn return_owned_and_referenced() -> OwningRef<Vec<u8>, [u8]> {
    let v = vec![1, 2, 3, 4];
    let or = OwningRef::new(v);
    let or = or.map(|v| &v[1..3]);
    or
}

It works by requiring owner types to dereference to stable memory locations and preventing mutable access to root containers, which in practice requires heap allocation as provided by Box<T>, Rc<T>, etc.

Also provided are typedefs for common owner type combinations, which allow for less verbose type signatures. For example, BoxRef<T> instead of OwningRef<Box<T>, T>.

The crate also provides the more advanced OwningHandle type, which allows more freedom in bundling a dependent handle object along with the data it depends on, at the cost of some unsafe needed in the API. See the documentation around OwningHandle for more details.

Examples

Basics

extern crate owning_ref;
use owning_ref::BoxRef;

fn main() {
    // Create an array owned by a Box.
    let arr = Box::new([1, 2, 3, 4]) as Box<[i32]>;

    // Transfer into a BoxRef.
    let arr: BoxRef<[i32]> = BoxRef::new(arr);
    assert_eq!(&*arr, &[1, 2, 3, 4]);

    // We can slice the array without losing ownership or changing type.
    let arr: BoxRef<[i32]> = arr.map(|arr| &arr[1..3]);
    assert_eq!(&*arr, &[2, 3]);

    // Also works for Arc, Rc, String and Vec!
}

Caching a reference to a struct field

extern crate owning_ref;
use owning_ref::BoxRef;

fn main() {
    struct Foo {
        tag: u32,
        x: u16,
        y: u16,
        z: u16,
    }
    let foo = Foo { tag: 1, x: 100, y: 200, z: 300 };

    let or = BoxRef::new(Box::new(foo)).map(|foo| {
        match foo.tag {
            0 => &foo.x,
            1 => &foo.y,
            2 => &foo.z,
            _ => panic!(),
        }
    });

    assert_eq!(*or, 200);
}

Caching a reference to an entry in a vector

extern crate owning_ref;
use owning_ref::VecRef;

fn main() {
    let v = VecRef::new(vec![1, 2, 3, 4, 5]).map(|v| &v[3]);
    assert_eq!(*v, 4);
}

Caching a subslice of a String

extern crate owning_ref;
use owning_ref::StringRef;

fn main() {
    let s = StringRef::new("hello world".to_owned())
        .map(|s| s.split(' ').nth(1).unwrap());

    assert_eq!(&*s, "world");
}

Reference counted slices that share ownership of the backing storage

extern crate owning_ref;
use owning_ref::RcRef;
use std::rc::Rc;

fn main() {
    let rc: RcRef<[i32]> = RcRef::new(Rc::new([1, 2, 3, 4]) as Rc<[i32]>);
    assert_eq!(&*rc, &[1, 2, 3, 4]);

    let rc_a: RcRef<[i32]> = rc.clone().map(|s| &s[0..2]);
    let rc_b = rc.clone().map(|s| &s[1..3]);
    let rc_c = rc.clone().map(|s| &s[2..4]);
    assert_eq!(&*rc_a, &[1, 2]);
    assert_eq!(&*rc_b, &[2, 3]);
    assert_eq!(&*rc_c, &[3, 4]);

    let rc_c_a = rc_c.clone().map(|s| &s[1]);
    assert_eq!(&*rc_c_a, &4);
}

Atomic reference counted slices that share ownership of the backing storage

extern crate owning_ref;
use owning_ref::ArcRef;
use std::sync::Arc;

fn main() {
    use std::thread;

    fn par_sum(rc: ArcRef<[i32]>) -> i32 {
        if rc.len() == 0 {
            return 0;
        } else if rc.len() == 1 {
            return rc[0];
        }
        let mid = rc.len() / 2;
        let left = rc.clone().map(|s| &s[..mid]);
        let right = rc.map(|s| &s[mid..]);

        let left = thread::spawn(move || par_sum(left));
        let right = thread::spawn(move || par_sum(right));

        left.join().unwrap() + right.join().unwrap()
    }

    let rc: Arc<[i32]> = Arc::new([1, 2, 3, 4]);
    let rc: ArcRef<[i32]> = rc.into();

    assert_eq!(par_sum(rc), 10);
}

References into RAII locks

extern crate owning_ref;
use owning_ref::RefRef;
use std::cell::{RefCell, Ref};

fn main() {
    let refcell = RefCell::new((1, 2, 3, 4));
    // Also works with Mutex and RwLock

    let refref = {
        let refref = RefRef::new(refcell.borrow()).map(|x| &x.3);
        assert_eq!(*refref, 4);

        // We move the RAII lock and the reference to one of
        // the subfields in the data it guards here:
        refref
    };

    assert_eq!(*refref, 4);

    drop(refref);

    assert_eq!(*refcell.borrow(), (1, 2, 3, 4));
}

Mutable reference

When the owned container implements DerefMut, it is also possible to make a mutable owning reference. (e.g., with Box, RefMut, MutexGuard)

extern crate owning_ref;
use owning_ref::RefMutRefMut;
use std::cell::{RefCell, RefMut};

fn main() {
    let refcell = RefCell::new((1, 2, 3, 4));

    let mut refmut_refmut = {
        let mut refmut_refmut = RefMutRefMut::new(refcell.borrow_mut()).map_mut(|x| &mut x.3);
        assert_eq!(*refmut_refmut, 4);
        *refmut_refmut *= 2;

        refmut_refmut
    };

    assert_eq!(*refmut_refmut, 8);
    *refmut_refmut *= 2;

    drop(refmut_refmut);

    assert_eq!(*refcell.borrow(), (1, 2, 3, 16));
}

Structs

OwningHandleInternal

OwningHandle is a complement to OwningRef. Where OwningRef allows consumers to pass around an owned object and a dependent reference, OwningHandle contains an owned object and a dependent object.

OwningRefInternal

An owning reference.

OwningRefMutInternal

An mutable owning reference.

Traits

CloneStableAddressInternal

An unsafe marker trait for types where clones deref to the same address. This has all the requirements of StableDeref, and additionally requires that after calling clone(), both the old and new value deref to the same address. For example, Rc and Arc implement CloneStableDeref, but Box and Vec do not.

ErasedInternal

Helper trait for an erased concrete type an owner dereferences to. This is used in form of a trait object for keeping something around to (virtually) call the destructor.

IntoErasedInternal

Helper trait for erasing the concrete type of what an owner dereferences to, for example Box<T> -> Box<Erased>. This would be unneeded with higher kinded types support in the language.

IntoErasedSendInternal

Helper trait for erasing the concrete type of what an owner dereferences to, for example Box<T> -> Box<Erased + Send>. This would be unneeded with higher kinded types support in the language.

IntoErasedSendSyncInternal

Helper trait for erasing the concrete type of what an owner dereferences to, for example Box<T> -> Box<Erased + Send + Sync>. This would be unneeded with higher kinded types support in the language.

StableAddressInternal

An unsafe marker trait for types that deref to a stable address, even when moved. For example, this is implemented by Box, Vec, Rc, Arc and String, among others. Even when a Box is moved, the underlying storage remains at a fixed location.

ToHandleInternal

Trait to implement the conversion of owner to handle for common types.

ToHandleMutInternal

Trait to implement the conversion of owner to mutable handle for common types.

Type Definitions

ArcRefInternal

Typedef of a owning reference that uses a Arc as the owner.

BoxRefInternal

Typedef of a owning reference that uses a Box as the owner.

BoxRefMutInternal

Typedef of a mutable owning reference that uses a Box as the owner.

ErasedArcRefInternal

Typedef of a owning reference that uses an erased Arc as the owner.

ErasedBoxRefInternal

Typedef of a owning reference that uses an erased Box as the owner.

ErasedBoxRefMutInternal

Typedef of a mutable owning reference that uses an erased Box as the owner.

ErasedRcRefInternal

Typedef of a owning reference that uses an erased Rc as the owner.

MutexGuardRefInternal

Typedef of a owning reference that uses a MutexGuard as the owner.

MutexGuardRefMutInternal

Typedef of a mutable owning reference that uses a MutexGuard as the owner.

RcRefInternal

Typedef of a owning reference that uses a Rc as the owner.

RefMutRefInternal

Typedef of a owning reference that uses a RefMut as the owner.

RefMutRefMutInternal

Typedef of a mutable owning reference that uses a RefMut as the owner.

RefRefInternal

Typedef of a owning reference that uses a Ref as the owner.

RwLockReadGuardRefInternal

Typedef of a owning reference that uses a RwLockReadGuard as the owner.

RwLockWriteGuardRefInternal

Typedef of a owning reference that uses a RwLockWriteGuard as the owner.

RwLockWriteGuardRefMutInternal

Typedef of a mutable owning reference that uses a RwLockWriteGuard as the owner.

StringRefInternal

Typedef of a owning reference that uses a String as the owner.

StringRefMutInternal

Typedef of a mutable owning reference that uses a String as the owner.

VecRefInternal

Typedef of a owning reference that uses a Vec as the owner.

VecRefMutInternal

Typedef of a mutable owning reference that uses a Vec as the owner.