1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
//! A macro to generate self-borrowing structs.
//! 
//! # 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 quite flexible, but can't quite express such a scenario yet.
//!
//! Creating such a struct manually requires unsafe code to erase lifetime parameters from the field types. Accessing such a field directly would be completely unsafe as a result. This library addresses the 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.
//! 
//! The API of this crate consists of the [`rental`](macro.rental.html) macro, which generates self-referential structs, and a few example instantiations to demonstrate the API provided by such structs (see [`RentRef`](examples/struct.RentRef.html), [`RentMut`](examples/struct.RentMut.html), [`RentRefMap`](examples/struct.RentRefMap.html), and [`RentMutMap`](examples/struct.RentMutMap.html)).
//! 
//! # Use Cases
//! One instance where this crate is useful is when working with `libloading`. That crate provides a `Library` struct that defines methods to borrow `Symbol`s 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:
//! 
//! ```rust,ignore
//! rental! {
//!     pub mod rent_libloading {
//!         use libloading;
//! 
//!         #[rental(deref_suffix)] // This struct will deref to the target of Symbol.
//!         pub struct RentSymbol<S: 'static> {
//!             lib: Box<libloading::Library>, // Library is boxed for stable deref.
//!             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.
//! 
//! For a more advanced case, let's take a look at the `alto` OpenAL bindings. Alto defines an `Alto` struct that represents the API, from which we can borrow an output `Device`, from which we can borrow a device `Context`. This is a 3-level self-referential relationship, but rental can handle it just fine:
//! 
//! ```rust,ignore
//! rental! {
//!     pub mod rent_alto {
//!         use alto;
//! 
//!         #[rental]
//!         pub struct RentContext {
//!             alto: Box<alto::Alto>,
//!             dev: Box<alto::Device<'alto>>,
//!             ctx: alto::Context<'dev>,
//!         }
//!     }
//! }
//! 
//! fn main() {
//!     let alto = alto::Alto::load_default().unwrap(); // Load the default OpenAL impl.
//!     if let Ok(rent_ctx) = rent_alto::RentContext::try_new(
//!         Box::new(alto),
//!         |alto| alto.open(None).map(|dev| Box::new(dev)), // Open the default device.
//!         |dev, _alto| dev.new_context(None), // Create a new context for our device.
//!     ) {
//!         rent_ctx.rent(|ctx| {
//!             // Do stuff with our context
//!         });
//!     };
//! }
//! ```
//! 
//! This approach can be extended to as many fields as you like, up to a current implementation defined maximum (see Limitations section).
//! 
//! # Limitations
//! There are a few limitations with the current implementation. These limitations aren't fundamental, but rather the result of bugs or pending features in rust itself, and will be lifted once the underlying language allows it.
//! 
//! * Currently, the rental struct itself cannot take lifetime parameters, and any type parameters it takes must be `'static`. In most situations this is fine, since most of the use cases for this library involve erasing all of the lifetimes anyway, but there's no reason why the head element of a rental struct shouldn't be able to be non-`'static`. This is currently impossible to implement due to lack of an `'unsafe` lifetime or equivalent feature.
//! * Prefix fields must be of the form `Foo<T>` where `Foo` is some `StableDeref` container, or rental will not be able to correctly guess the `Deref::Target` of the type. If you are using a custom type that does not fit this pattern, you can use the `target_ty_hack` attribute on the field to manually specify the target type. This limitation can be lifted once rust gets ATC or possibly after current bugs surrounding HRTB associated item unification are fixed. The requirement for `StableDeref` at all can possibly be lifted if rust gains a notion of immovable types.
//! * Rental structs can only have a maximum of 32 rental lifetimes, including transitive rental lifetimes from subrentals. This limitation is the result of needing to implement a new trait for each rental arity. More traits can easily be defined though. Lifting this limitation entirely would require some kind of variadic lifetime generics.
//! * The references received in the constructor closures don't currently have their lifetime relationship expressed in bounds. This is currently not possible until the trait system refactor lands. This is not a soundness hole, but it does prevent some otherwise valid uses from compiling.


#![cfg_attr(not(feature = "std"), no_std)]

#[cfg(feature = "std")]
extern crate core;
#[macro_use]
extern crate rental_impl;
extern crate stable_deref_trait;

#[doc(hidden)]
pub use rental_impl::*;


/// This trait converts any `*_Borrow` or `*_BorrowMut` structs generated by the [`rental`](macro.rental.html) macro into their suffix (most dependent) field.
///
/// When you own a borrow struct, such as in the body of the closure provided to the `rent_all` or `ref_rent_all` methods of a rental struct, you can call `into_suffix()` to discard the borrow struct and obtain the suffix field if you don't need any of the other fields.
pub trait IntoSuffix {
	/// Type of the transitive suffix of the borrow struct.
	///
	/// If the suffix field of the borrow struct is itself a borrow struct of a subrental, then this type is the suffix of that nested borrow struct, recursively.
	type Suffix;

	/// Discard the borrow struct and return the transitive suffix field.
	///
	/// If the suffix field of the borrow struct is itself a borrow struct of a subrental, then this function will return the nested suffix of that borrow struct, recursively.
	fn into_suffix(self) -> <Self as IntoSuffix>::Suffix;
}


/// An error wrapper returned by the `try_new` method of a rental struct.
///
/// This will contain the first error returned by the closure chain, as well as the original head value you passed in so you can do something else with it.
pub struct TryNewError<E, H> (pub E, pub H);

pub type TryNewResult<T, E, H> = Result<T, TryNewError<E, H>>;


macro_rules! define_rental_traits {
	($max_arity:expr) => {
		#[allow(unused)]
		#[derive(__rental_traits)]
		enum ProceduralMasqueradeDummyType {
			Input = (0, stringify!($max_arity)).0
		}
	};
}


#[doc(hidden)]
pub mod __rental_prelude {
	pub use core::marker::PhantomData;
	pub use core::ops::{Deref, DerefMut, Drop};
	pub use core::convert::{AsRef, AsMut, Into};
	pub use core::borrow::{Borrow, BorrowMut};
	pub use core::mem::transmute;
	pub use core::result::Result;
	pub use core::option::Option;
	pub use core::fmt;
	pub use stable_deref_trait::StableDeref;

	pub use super::{IntoSuffix, TryNewError, TryNewResult};


	define_rental_traits!(32);


	#[inline(always)]
	pub fn static_assert_stable_deref<T: StableDeref>() { }
}


/// The core of this crate, this macro will generate self-referential structs.
/// 
/// This macro is invoked in item position. The body parses as valid rust and contains no special syntax. Only certain constructs are allowed, and a few special attributes and lifetimes are recognized.
/// 
/// To start, the the top level item of the macro invocation must be a single module. This module will contain all items that the macro generates and export them to you. Within the module, only two types of items are accepted: `use` statements and struct definitions. The `use` statements are passed directly through with no special consideration; the primary concern is the struct definitions.
/// 
/// First, all struct definitions must have a `#[rental]` or `#[rental_mut]` attribute to indicate that they are self-referential. These attributes may optionally take the option arguments of `debug_borrow`, `deref_suffix`, and `deref_mut_suffix`, discussed below.
/// 
/// Next, the structs must have named fields (no tuple structs) and they must have at least 2 fields, since a struct with 1 field can't meaningfully reference itself anyway.
/// 
/// The order of the fields is significant, as they are declared in order of least to most dependent. The first field, also referred to as the "head" of the struct, contains no self-references, the second field may borrow the first, the third field may borrow the second or first, and so on. The chain of fields after the head is called the "tail".
/// 
/// Because rental structs are self-referential, special care is taken to ensure that moving the struct will not invalidate any internal references. This is accomplished by requiring all fields but the last one, collectively known as the "prefix" of the struct, to implement [`StableDeref`](https://crates.io/crates/stable_deref_trait). This is not required for the final field of the struct, known as the "suffix", since nothing holds a reference to it.
///
/// NOTE: Because of a workaround for a compiler bug, rental might not always correctly determine the `Deref::Target` type of your prefix fields. If you receive type errors when compiling, you can try using the `target_ty_hack` attribute on the field of the struct. Set this attribute equal to a string that names the correct target type (e.g. `#[target_ty_hack = "[u8]"]` for `Vec<u8>`.
/// 
/// Each field that you declare creates a special lifetime of the same name that can be used by later fields to borrow it. This is how the referential relationships are established in the struct definition.
/// 
/// This is a all a bit to chew on so far, so let's stop and take a look at an example:
///
/// ```rust
/// # #[macro_use] extern crate rental;
/// pub struct Foo { i: i32 }
/// pub struct Bar<'a> { foo: &'a Foo }
/// pub struct Qux<'a: 'b, 'b> { bar: &'b Bar<'a> }
/// 
/// rental! {
///     mod my_rentals {
///         use super::*;
///
///         #[rental]
///         pub struct MyRental {
///             foo: Box<Foo>,
///             bar: Box<Bar<'foo>>,
///             qux: Qux<'foo, 'bar>,
///         }
///     }
/// }
/// # fn main () { }
/// ```
/// 
/// Here we see each field use the special lifetimes of the previous fields to establish the borrowing chain.
/// 
/// In addition to the rental struct itself, two other structs are generated, with `_Borrow` and `_BorrowMut` appended to the original struct name (e.g. `MyRental_Borrow` and `MyRental_BorrowMut`). These structs contain the same fields as the original struct, but are borrows of the originals. These structs are passed into certain closures that you provide to allow you access to underlying struct data. The `Mut` version only allows access to the suffix, but as a mutable rather than shared borrow.
/// 
/// If all the fields of your struct implement `Debug` then you can use the `debug_borrow` option on the rental attribute to gain a `Debug` impl on the struct itself. Also, if the suffix field of the struct implements `Deref` or `DerefMut`, you can add a `deref_suffix` or `deref_mut_suffix` argument to the `rental` attribute on the struct. This will generate a `Deref` implementation for the rental struct itself that will deref through the suffix and return the borrow to you, for convenience. Note, however, that this will only be legal if none of the special rental lifetimes appear in the type signature of the deref target. If they do, exposing them to the outside world could result in unsafety, so this is not allowed and such a scenario will not compile.
/// 
/// Finally, there is one other capability to discuss. If a rental struct has been defined elsewhere, either in our own crate or in a dependency, we'd like to be able to chain our own rental struct off of it. In this way, we can use another rental struct as a sort of pre-packaged prefix of our own. As a variation on the above example, it would look like this:
///
/// ```rust
/// # #[macro_use] extern crate rental;
/// pub struct Foo { i: i32 }
/// pub struct Bar<'a> { foo: &'a Foo }
/// pub struct Qux<'a: 'b, 'b> { bar: &'b Bar<'a> }
/// 
/// rental! {
///     mod my_rentals {
///         use super::*;
///
///         #[rental]
///         pub struct OtherRental {
///             foo: Box<Foo>,
///             bar: Bar<'foo>,
///         }
///         
///         #[rental]
///         pub struct MyRental {
///             #[subrental(arity = 2)]
///             prefix: Box<OtherRental>,
///             qux: Qux<'prefix_0, 'prefix_1>,
///         }
///     }
/// }
/// # fn main () { }
/// ```
/// 
/// The first rental struct is fairly standard, so we'll focus on the second one. The head field is given a `subrental` attribute with an `arity` argument. The arity of a rental struct is the number of special lifetimes it creates. As can be seen above, the first struct has two fields, neither of which is itself a subrental, so it has an arity of 2. The arity of the second struct would be 3, since it includes the two fields of the first rental as well as one new one. In this way, arity is transitive. So if we used our new struct itself as a subrental of yet another struct, we'd need to declare the field with `arity = 3`. The special lifetimes created by a subrental are the field named, followed by a `_` and a zero-based index.
/// 
/// This covers the essential capabilities of the macro itself. For details on the API of the structs themselves, see the [`examples`](examples/index.html) module.
#[macro_export]
macro_rules! rental {
	{
		$(#[$attr:meta])*
		mod $rental_mod:ident {
			$($body:tt)*
		}
	} => {
		$(#[$attr])*
		mod $rental_mod {
			#[allow(unused_imports)]
			use $crate::__rental_prelude;

			#[allow(unused)]
			#[derive(__rental_structs_and_impls)]
			enum ProceduralMasqueradeDummyType {
				Input = (0, stringify!($($body)*)).0
			}
		}
	};
	{
		$(#[$attr:meta])*
		pub mod $rental_mod:ident {
			$($body:tt)*
		}
	} => {
		$(#[$attr])*
		pub mod $rental_mod {
			#[allow(unused_imports)]
			use $crate::__rental_prelude;

			#[allow(unused)]
			#[derive(__rental_structs_and_impls)]
			enum ProceduralMasqueradeDummyType {
				Input = (0, stringify!($($body)*)).0
			}
		}
	};
	{
		$(#[$attr:meta])*
		pub($($vis:tt)*) mod $rental_mod:ident {
			$($body:tt)*
		}
	} => {
		$(#[$attr])*
		pub($($vis)*) mod $rental_mod {
			#[allow(unused_imports)]
			use $crate::__rental_prelude;

			#[allow(unused)]
			#[derive(__rental_structs_and_impls)]
			enum ProceduralMasqueradeDummyType {
				Input = (0, stringify!($($body)*)).0
			}
		}
	};
}


#[cfg(feature = "std")]
rental! {
	/// Example instantiations that demonstrate the API provided by the types this crate generates.
	pub mod examples {
		/// A simple example that can store an owner and a shared reference in the same struct.
		///
		/// ```rust
		/// # extern crate rental;
		/// # use rental::examples::RentRef;
		/// # fn main() {
		/// let r = RentRef::new(Box::new(5), |i| &*i);
		/// assert_eq!(*r, r.rent(|iref| **iref));
		/// # }
		/// ```
		#[rental(deref_suffix)]
		pub struct RentRef<T: 'static, U: 'static> {
			head: Box<T>,
			suffix: &'head U,
		}

		/// A simple example that can store an owner and a mutable reference in the same struct.
		///
		/// ```rust
		/// # extern crate rental;
		/// # use rental::examples::RentMut;
		/// # fn main() {
		/// let mut r = RentMut::new(Box::new(5), |i| &mut *i);
		/// *r = 12;
		/// assert_eq!(12, r.rent(|iref| **iref));
		/// # }
		/// ```
		#[rental_mut(deref_mut_suffix)]
		pub struct RentMut<T: 'static, U: 'static> {
			head: Box<T>,
			suffix: &'head mut U,
		}

		/// An example that borrows off of another rental struct.
		///
		/// ```rust
		/// # extern crate rental;
		/// # use rental::examples::{RentRef, RentRefMap};
		/// # fn main() {
		/// let r = RentRef::new(Box::new(5), |i| &*i);
		/// let rm = RentRefMap::new(Box::new(r), |r| &**r.suffix);
		/// assert_eq!(*rm, rm.rent(|iref| **iref));
		/// # }
		/// ```
		#[rental(deref_suffix)]
		pub struct RentRefMap<T: 'static, U: 'static, V: 'static> {
			#[subrental(arity = 2)]
			head: Box<RentRef<T, U>>,
			suffix: &'head_1 V,
		}

		/// An example that borrows mutably off of another rental struct.
		///
		/// ```rust
		/// # extern crate rental;
		/// # use rental::examples::{RentMut, RentMutMap};
		/// # fn main() {
		/// let mut r = RentMut::new(Box::new(5), |i| &mut *i);
		/// let mut rm = RentMutMap::new(Box::new(r), |r| &mut **r.suffix);
		/// *rm = 12;
		/// assert_eq!(12, rm.rent(|iref| **iref));
		/// # }
		/// ```
		#[rental_mut(deref_mut_suffix)]
		pub struct RentMutMap<T: 'static, U: 'static, V: 'static> {
			#[subrental(arity = 2)]
			head: Box<RentMut<T, U>>,
			suffix: &'head_1 mut V,
		}
	}
}