[][src]Crate rental

A macro to generate safe self-referntial structs, plus premade types for common use cases.

Overview

It can sometimes occur in the course of designing an API that it would be convenient, or even necessary, to allow fields within a struct to hold references to other fields within that same struct. Rust's concept of ownership and borrowing is powerful, but can't express such a scenario yet.

Creating such a struct manually would require unsafe code to erase lifetime parameters from the field types. Accessing the fields directly would be completely unsafe as a result. This library addresses that issue by allowing access to the internal fields only under carefully controlled circumstances, through closures that are bounded by generic lifetimes to prevent infiltration or exfiltration of any data with an incorrect lifetime. In short, while the struct internally uses unsafe code to store the fields, the interface exposed to the consumer of the struct is completely safe. The implementation of this interface is subtle and verbose, hence the macro to automate the process.

The API of this crate consists of the rental macro that generates safe self-referential structs, a few example instantiations to demonstrate the API provided by such structs (see examples), and a module of premade instantiations to cover common use cases (see common).

Example

One instance where this crate is useful is when working with libloading. That crate provides a Library struct that defines methods to borrow Symbols from it. These symbols are bounded by the lifetime of the library, and are thus considered a borrow. Under normal circumstances, one would be unable to store both the library and the symbols within a single struct, but the macro defined in this crate allows you to define a struct that is capable of storing both simultaneously, like so:

This example is not tested
rental! {
    pub mod rent_libloading {
        use libloading;
 
        #[rental(deref_suffix)] // This struct will deref to the Deref::Target of Symbol.
        pub struct RentSymbol<S: 'static> {
            lib: Box<libloading::Library>, // Library is boxed for StableDeref.
            sym: libloading::Symbol<'lib, S>, // The 'lib lifetime borrows lib.
        }
    }
}
 
fn main() {
    let lib = libloading::Library::new("my_lib.so").unwrap(); // Open our dylib.
    if let Ok(rs) = rent_libloading::RentSymbol::try_new(
        Box::new(lib),
        |lib| unsafe { lib.get::<extern "C" fn()>(b"my_symbol") }) // Loading symbols is unsafe.
    {
        (*rs)(); // Call our function
    };
}

In this way we can store both the Library and the Symbol that borrows it in a single struct. We can even tell our struct to deref to the function pointer itself so we can easily call it. This is legal because the function pointer does not contain any of the special lifetimes introduced by the rental struct in its type signature, which means reborrowing will not expose them to the outside world. As an aside, the unsafe block for loading the symbol is necessary because the act of loading a symbol from a dylib is unsafe, and is unrelated to rental.

NOTE for Rust 2018: Relying on implicit crate imports may cause compile errors in code generated by this macro. To avoid this, import the crate manually like so:

This example is not tested
#[macro_use]
extern crate rental; 

Limitations

There are a few limitations with the current implementation due to bugs or pending features in rust itself. These will be lifted once the underlying language allows it.

Modules

common

Premade types for the most common use cases.

examples

Example types that demonstrate the API generated by the rental macro.

Macros

rental

The bedrock of this crate, this macro will generate self-referential structs.

Structs

RentalError

An error wrapper returned by the try_new method of a rental struct.

Traits

IntoSuffix

This trait converts any *_Borrow or *_BorrowMut structs generated by the rental macro into their suffix (most dependent) field.

Type Definitions

RentalResult