Use core::mem::ManuallyDrop instead of implementing our own NoDrop
This commit is contained in:
parent
5849a2d330
commit
17c41ce777
|
@ -14,6 +14,7 @@
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::{ptr, mem};
|
use core::{ptr, mem};
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
|
use core::mem::ManuallyDrop;
|
||||||
|
|
||||||
use stack;
|
use stack;
|
||||||
use debug;
|
use debug;
|
||||||
|
@ -84,26 +85,12 @@ pub enum State {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Generator<'a, Input: 'a, Output: 'a, Stack: stack::Stack> {
|
pub struct Generator<'a, Input: 'a, Output: 'a, Stack: stack::Stack> {
|
||||||
state: State,
|
state: State,
|
||||||
stack: NoDrop<Stack>,
|
stack: ManuallyDrop<Stack>,
|
||||||
stack_id: NoDrop<debug::StackId>,
|
stack_id: ManuallyDrop<debug::StackId>,
|
||||||
stack_ptr: arch::StackPointer,
|
stack_ptr: arch::StackPointer,
|
||||||
phantom: PhantomData<(&'a (), *mut Input, *const Output)>
|
phantom: PhantomData<(&'a (), *mut Input, *const Output)>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unions_with_drop_fields)]
|
|
||||||
union NoDrop<T> {
|
|
||||||
inner: T
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ::core::fmt::Debug> ::core::fmt::Debug for NoDrop<T> {
|
|
||||||
fn fmt(&self, w: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
|
||||||
unsafe {
|
|
||||||
// this is safe because we never invoke formatting on the empty variant
|
|
||||||
self.inner.fmt(w)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, Input, Output, Stack> Generator<'a, Input, Output, Stack>
|
impl<'a, Input, Output, Stack> Generator<'a, Input, Output, Stack>
|
||||||
where Input: 'a, Output: 'a, Stack: stack::Stack {
|
where Input: 'a, Output: 'a, Stack: stack::Stack {
|
||||||
/// Creates a new generator.
|
/// Creates a new generator.
|
||||||
|
@ -147,8 +134,8 @@ impl<'a, Input, Output, Stack> Generator<'a, Input, Output, Stack>
|
||||||
|
|
||||||
Generator {
|
Generator {
|
||||||
state: State::Runnable,
|
state: State::Runnable,
|
||||||
stack: NoDrop { inner: stack },
|
stack: ManuallyDrop::new(stack),
|
||||||
stack_id: NoDrop { inner: stack_id },
|
stack_id: ManuallyDrop::new(stack_id),
|
||||||
stack_ptr: stack_ptr,
|
stack_ptr: stack_ptr,
|
||||||
phantom: PhantomData
|
phantom: PhantomData
|
||||||
}
|
}
|
||||||
|
@ -167,7 +154,7 @@ impl<'a, Input, Output, Stack> Generator<'a, Input, Output, Stack>
|
||||||
|
|
||||||
// Switch to the generator function, and retrieve the yielded value.
|
// Switch to the generator function, and retrieve the yielded value.
|
||||||
let val = unsafe {
|
let val = unsafe {
|
||||||
let (data_out, stack_ptr) = arch::swap(&input as *const Input as usize, self.stack_ptr, Some(&self.stack.inner));
|
let (data_out, stack_ptr) = arch::swap(&input as *const Input as usize, self.stack_ptr, Some(&*self.stack));
|
||||||
self.stack_ptr = stack_ptr;
|
self.stack_ptr = stack_ptr;
|
||||||
mem::forget(input);
|
mem::forget(input);
|
||||||
ptr::read(data_out as *const Option<Output>)
|
ptr::read(data_out as *const Option<Output>)
|
||||||
|
@ -203,8 +190,8 @@ impl<'a, Input, Output, Stack> Generator<'a, Input, Output, Stack>
|
||||||
/// Extracts the stack from a generator without checking if the generator function has returned.
|
/// Extracts the stack from a generator without checking if the generator function has returned.
|
||||||
/// This will leave any pointers into the generator stack dangling, and won't run destructors.
|
/// This will leave any pointers into the generator stack dangling, and won't run destructors.
|
||||||
pub unsafe fn unsafe_unwrap(mut self) -> Stack {
|
pub unsafe fn unsafe_unwrap(mut self) -> Stack {
|
||||||
ptr::drop_in_place(&mut self.stack_id.inner);
|
ManuallyDrop::drop(&mut self.stack_id);
|
||||||
let stack = ptr::read(&mut self.stack.inner);
|
let stack = ptr::read(&mut *self.stack);
|
||||||
mem::forget(self);
|
mem::forget(self);
|
||||||
stack
|
stack
|
||||||
}
|
}
|
||||||
|
@ -214,10 +201,10 @@ impl<'a, Input, Output, Stack> Drop for Generator<'a, Input, Output, Stack>
|
||||||
where Input: 'a, Output: 'a, Stack: stack::Stack {
|
where Input: 'a, Output: 'a, Stack: stack::Stack {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
ptr::drop_in_place(&mut self.stack_id.inner);
|
ManuallyDrop::drop(&mut self.stack_id);
|
||||||
match self.state {
|
match self.state {
|
||||||
State::Runnable => panic!("dropped unfinished Generator"),
|
State::Runnable => panic!("dropped unfinished Generator"),
|
||||||
State::Unavailable => ptr::drop_in_place(&mut self.stack.inner)
|
State::Unavailable => ManuallyDrop::drop(&mut self.stack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue