Ensure that the closure outlives the generator [breaking-change]

Previously, it was possible to cause unsafety by having the closure
refer to values with lifetimes that weren't enclosed by the generator's
lifetime.
This commit is contained in:
edef 2016-09-14 15:18:31 -04:00
parent adb29eade7
commit 59f28e92cb
2 changed files with 10 additions and 10 deletions

View File

@ -80,22 +80,22 @@ pub enum State {
/// println!("{:?}", nat.next()); // prints Some(2) /// println!("{:?}", nat.next()); // prints Some(2)
/// ``` /// ```
#[derive(Debug)] #[derive(Debug)]
pub struct Generator<Input: Send, Output: Send, Stack: stack::Stack> { pub struct Generator<'a, Input: Send, Output: Send, Stack: stack::Stack> {
state: State, state: State,
stack: Stack, stack: Stack,
stack_id: debug::StackId, stack_id: debug::StackId,
stack_ptr: arch::StackPointer, stack_ptr: arch::StackPointer,
phantom: PhantomData<(*mut Input, *const Output)> phantom: PhantomData<(&'a (), *mut Input, *const Output)>
} }
impl<Input, Output, Stack> Generator<Input, Output, Stack> impl<'a, Input, Output, Stack> Generator<'a, Input, Output, Stack>
where Input: Send, Output: Send, Stack: stack::Stack { where Input: Send, Output: Send, Stack: stack::Stack {
/// Creates a new generator. /// Creates a new generator.
/// ///
/// See also the [contract](../trait.GuardedStack.html) that needs to be fulfilled by `stack`. /// See also the [contract](../trait.GuardedStack.html) that needs to be fulfilled by `stack`.
pub fn new<F>(stack: Stack, f: F) -> Generator<Input, Output, Stack> pub fn new<F>(stack: Stack, f: F) -> Generator<'a, Input, Output, Stack>
where Stack: stack::GuardedStack, where Stack: stack::GuardedStack,
F: FnOnce(&mut Yielder<Input, Output>, Input) + Send { F: FnOnce(&mut Yielder<Input, Output>, Input) + Send + 'a {
unsafe { Generator::unsafe_new(stack, f) } unsafe { Generator::unsafe_new(stack, f) }
} }
@ -106,8 +106,8 @@ impl<Input, Output, Stack> Generator<Input, Output, Stack>
/// guarded stacks do not exist, e.g. in absence of an MMU. /// guarded stacks do not exist, e.g. in absence of an MMU.
/// ///
/// See also the [contract](../trait.Stack.html) that needs to be fulfilled by `stack`. /// See also the [contract](../trait.Stack.html) that needs to be fulfilled by `stack`.
pub unsafe fn unsafe_new<F>(stack: Stack, f: F) -> Generator<Input, Output, Stack> pub unsafe fn unsafe_new<F>(stack: Stack, f: F) -> Generator<'a, Input, Output, Stack>
where F: FnOnce(&mut Yielder<Input, Output>, Input) + Send { where F: FnOnce(&mut Yielder<Input, Output>, Input) + Send + 'a {
unsafe extern "C" fn generator_wrapper<Input, Output, Stack, F>(env: usize, stack_ptr: StackPointer) -> ! unsafe extern "C" fn generator_wrapper<Input, Output, Stack, F>(env: usize, stack_ptr: StackPointer) -> !
where Input: Send, Output: Send, Stack: stack::Stack, where Input: Send, Output: Send, Stack: stack::Stack,
F: FnOnce(&mut Yielder<Input, Output>, Input) { F: FnOnce(&mut Yielder<Input, Output>, Input) {
@ -218,7 +218,7 @@ impl<Input, Output> Yielder<Input, Output>
} }
} }
impl<Output, Stack> Iterator for Generator<(), Output, Stack> impl<'a, Output, Stack> Iterator for Generator<'a, (), Output, Stack>
where Output: Send, Stack: stack::Stack { where Output: Send, Stack: stack::Stack {
type Item = Output; type Item = Output;

View File

@ -17,7 +17,7 @@ fn add_one_fn(yielder: &mut Yielder<i32, i32>, mut input: i32) {
} }
} }
fn new_add_one() -> Generator<i32, i32, OsStack> { fn new_add_one() -> Generator<'static, i32, i32, OsStack> {
let stack = OsStack::new(0).unwrap(); let stack = OsStack::new(0).unwrap();
Generator::new(stack, add_one_fn) Generator::new(stack, add_one_fn)
} }
@ -48,7 +48,7 @@ fn move_after_new() {
#[should_panic] #[should_panic]
fn panic_safety() { fn panic_safety() {
struct Wrapper { struct Wrapper {
gen: Generator<(), (), OsStack> gen: Generator<'static, (), (), OsStack>
} }
impl Drop for Wrapper { impl Drop for Wrapper {