From 59f28e92cbfd5b534bc5788a2b2c6be8bd258610 Mon Sep 17 00:00:00 2001 From: edef Date: Wed, 14 Sep 2016 15:18:31 -0400 Subject: [PATCH] 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. --- src/generator.rs | 16 ++++++++-------- tests/generator.rs | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/generator.rs b/src/generator.rs index b3b96a5..31b7116 100644 --- a/src/generator.rs +++ b/src/generator.rs @@ -80,22 +80,22 @@ pub enum State { /// println!("{:?}", nat.next()); // prints Some(2) /// ``` #[derive(Debug)] -pub struct Generator { +pub struct Generator<'a, Input: Send, Output: Send, Stack: stack::Stack> { state: State, stack: Stack, stack_id: debug::StackId, stack_ptr: arch::StackPointer, - phantom: PhantomData<(*mut Input, *const Output)> + phantom: PhantomData<(&'a (), *mut Input, *const Output)> } -impl Generator +impl<'a, Input, Output, Stack> Generator<'a, Input, Output, Stack> where Input: Send, Output: Send, Stack: stack::Stack { /// Creates a new generator. /// /// See also the [contract](../trait.GuardedStack.html) that needs to be fulfilled by `stack`. - pub fn new(stack: Stack, f: F) -> Generator + pub fn new(stack: Stack, f: F) -> Generator<'a, Input, Output, Stack> where Stack: stack::GuardedStack, - F: FnOnce(&mut Yielder, Input) + Send { + F: FnOnce(&mut Yielder, Input) + Send + 'a { unsafe { Generator::unsafe_new(stack, f) } } @@ -106,8 +106,8 @@ impl Generator /// 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`. - pub unsafe fn unsafe_new(stack: Stack, f: F) -> Generator - where F: FnOnce(&mut Yielder, Input) + Send { + pub unsafe fn unsafe_new(stack: Stack, f: F) -> Generator<'a, Input, Output, Stack> + where F: FnOnce(&mut Yielder, Input) + Send + 'a { unsafe extern "C" fn generator_wrapper(env: usize, stack_ptr: StackPointer) -> ! where Input: Send, Output: Send, Stack: stack::Stack, F: FnOnce(&mut Yielder, Input) { @@ -218,7 +218,7 @@ impl Yielder } } -impl Iterator for Generator<(), Output, Stack> +impl<'a, Output, Stack> Iterator for Generator<'a, (), Output, Stack> where Output: Send, Stack: stack::Stack { type Item = Output; diff --git a/tests/generator.rs b/tests/generator.rs index 174a378..30a8bfd 100644 --- a/tests/generator.rs +++ b/tests/generator.rs @@ -17,7 +17,7 @@ fn add_one_fn(yielder: &mut Yielder, mut input: i32) { } } -fn new_add_one() -> Generator { +fn new_add_one() -> Generator<'static, i32, i32, OsStack> { let stack = OsStack::new(0).unwrap(); Generator::new(stack, add_one_fn) } @@ -48,7 +48,7 @@ fn move_after_new() { #[should_panic] fn panic_safety() { struct Wrapper { - gen: Generator<(), (), OsStack> + gen: Generator<'static, (), (), OsStack> } impl Drop for Wrapper {