genawaiter_macro/
lib.rs

1#![warn(future_incompatible, rust_2018_compatibility, rust_2018_idioms, unused)]
2#![warn(clippy::cargo, clippy::pedantic)]
3#![cfg_attr(feature = "strict", deny(warnings))]
4
5#[macro_export]
6#[cfg(feature = "proc_macro")]
7macro_rules! stack_let_gen {
8    ($name:ident, $body:expr $(,)?) => {
9        ::genawaiter::stack::let_gen_using!(
10            $name,
11            ::genawaiter::stack_producer!($body),
12        );
13    };
14}
15
16#[macro_export]
17macro_rules! stack_let_gen_using {
18    ($name:ident, $producer:expr $(,)?) => {
19        // Safety: The goal here is to ensure the safety invariants of `Gen::new`, i.e.,
20        // the lifetime of the `Co` argument (in `$producer`) must not outlive `shelf`
21        // or `generator`.
22        //
23        // We create two variables, `shelf` and `generator`, which cannot be named by
24        // user-land code (because of macro hygiene). Because they are declared in the
25        // same scope, and cannot be dropped before the end of the scope (because they
26        // cannot be named), they have equivalent lifetimes. The type signature of
27        // `Gen::new` ties the lifetime of `co` to that of `shelf`. This means it has
28        // the same lifetime as `generator`, and so the invariant of `Gen::new` cannot
29        // be violated.
30        let mut shelf = ::genawaiter::stack::Shelf::new();
31        let mut generator =
32            unsafe { ::genawaiter::stack::Gen::new(&mut shelf, $producer) };
33        let $name = &mut generator;
34    };
35}
36
37#[macro_export]
38#[cfg(feature = "proc_macro")]
39macro_rules! rc_gen {
40    ($body:expr) => {
41        ::genawaiter::rc::Gen::new(::genawaiter::rc_producer!($body))
42    };
43}
44
45#[macro_export]
46#[cfg(feature = "proc_macro")]
47macro_rules! sync_gen {
48    ($body:expr) => {
49        ::genawaiter::sync::Gen::new(::genawaiter::sync_producer!($body))
50    };
51}