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
/**
Creates a generator on the stack.
This macro is deprecated. Use [`let_gen!`] or [`let_gen_using!`] instead.
[`let_gen!`]: stack/macro.let_gen.html
[`let_gen_using!`]: stack/macro.let_gen_using.html
*/
#[macro_export]
#[deprecated = "Use `let_gen_using!()` instead."]
macro_rules! generator_mut {
($name:ident, $producer:expr $(,)?) => {
$crate::stack::let_gen_using!($name, $producer);
};
}
/**
Creates a generator on the stack unsafely.
This macro is deprecated. Use [`let_gen!`] or [`let_gen_using!`] instead.
[`let_gen!`]: stack/macro.let_gen.html
[`let_gen_using!`]: stack/macro.let_gen_using.html
*/
#[macro_export]
#[deprecated = "Use `let_gen_using!()` instead."]
macro_rules! unsafe_create_generator {
($name:ident, $producer:expr $(,)?) => {
let mut generator_state = $crate::stack::Shelf::new();
#[allow(unused_mut)]
let mut $name =
unsafe { $crate::stack::Gen::new(&mut generator_state, $producer) };
};
}
#[cfg(test)]
mod tests {
use crate::{
ops::GeneratorState,
stack::{Co, Gen, Shelf},
};
/// This test proves that `Gen::new` is actually unsafe.
#[test]
#[ignore = "compile-only test"]
fn unsafety() {
async fn shenanigans(co: Co<'_, i32>) -> Co<'_, i32> {
co
}
let mut shelf = Shelf::new();
let mut gen = unsafe { Gen::new(&mut shelf, shenanigans) };
// Get the `co` out of the generator (don't try this at home).
let escaped_co = match gen.resume() {
GeneratorState::Yielded(_) => panic!(),
GeneratorState::Complete(co) => co,
};
// Drop the generator. This drops the airlock (inside the state), but `co` still
// holds a reference to the airlock.
drop(gen);
// Now we're able to use an invalidated reference.
let _ = escaped_co.yield_(10);
}
}
#[allow(dead_code)]
mod doctests {
/**
```compile_fail
use genawaiter::{stack::{let_gen_using, Co}, Generator};
async fn producer(co: Co<'_, i32>) {}
fn create_generator() -> impl Generator {
let_gen_using!(gen, producer);
gen
}
```
*/
fn generator_cannot_escape() {}
/**
This test is exactly the same as above, but doesn't trigger the failure.
```
use genawaiter::{stack::{let_gen_using, Co}, Generator};
async fn producer(co: Co<'_, i32>) {}
fn create_generator() { // -> impl Generator {
let_gen_using!(gen, producer);
// gen
}
```
*/
fn generator_cannot_escape_baseline() {}
}