diff --git a/benches/lib.rs b/benches/lib.rs index 50fff39..8dd69d0 100644 --- a/benches/lib.rs +++ b/benches/lib.rs @@ -1,4 +1,5 @@ #![feature(test)] +#![allow(deprecated)] extern crate generator; extern crate test; @@ -176,6 +177,6 @@ fn fnbox_bench(b: &mut Bencher) { let f: Box = Box::new(|| { test::black_box(a); }); - test::black_box(f); + let _ = test::black_box(f); }); } diff --git a/examples/cd.rs b/examples/cd.rs index 02a2804..18a5c9b 100644 --- a/examples/cd.rs +++ b/examples/cd.rs @@ -1,4 +1,3 @@ -extern crate generator; use generator::*; #[derive(Debug)] diff --git a/examples/fib.rs b/examples/fib.rs index e6c778f..4c3bd79 100644 --- a/examples/fib.rs +++ b/examples/fib.rs @@ -1,6 +1,4 @@ -#[macro_use] -extern crate generator; -use generator::Gn; +use generator::{done, Gn}; fn main() { let g = Gn::new_scoped(|mut s| { diff --git a/examples/get_yield.rs b/examples/get_yield.rs index 75ea814..644b72a 100644 --- a/examples/get_yield.rs +++ b/examples/get_yield.rs @@ -1,4 +1,4 @@ -extern crate generator; +#![allow(deprecated)] use generator::{get_yield, yield_with, Gn}; fn sum(a: u32) -> u32 { diff --git a/examples/number.rs b/examples/number.rs index 99628f6..5ea3ed2 100644 --- a/examples/number.rs +++ b/examples/number.rs @@ -1,4 +1,3 @@ -extern crate generator; use generator::*; fn factors(n: u32) -> Generator<'static, (), u32> { diff --git a/examples/pipe.rs b/examples/pipe.rs index 5de6302..43d0864 100644 --- a/examples/pipe.rs +++ b/examples/pipe.rs @@ -1,4 +1,3 @@ -extern crate generator; use generator::*; fn main() { diff --git a/examples/range.rs b/examples/range.rs index 34b85f0..a5589db 100644 --- a/examples/range.rs +++ b/examples/range.rs @@ -1,6 +1,4 @@ -#[macro_use] -extern crate generator; -use generator::Gn; +use generator::{done, Gn}; fn main() { let n = 100000; diff --git a/examples/send.rs b/examples/send.rs index 30f0226..cbc3c39 100644 --- a/examples/send.rs +++ b/examples/send.rs @@ -1,8 +1,7 @@ -extern crate generator; - -use std::mem; +#![allow(deprecated)] use generator::{yield_, Gn}; +use std::mem; fn sum(a: u32) -> u32 { let mut sum = a; diff --git a/examples/yield_from.rs b/examples/yield_from.rs index f26d1b8..893e6a3 100644 --- a/examples/yield_from.rs +++ b/examples/yield_from.rs @@ -1,4 +1,5 @@ -extern crate generator; +#![allow(deprecated)] + use generator::*; fn xrange(start: u32, end: u32) -> u32 { diff --git a/src/gen_impl.rs b/src/gen_impl.rs index 8f56304..ae6c56b 100644 --- a/src/gen_impl.rs +++ b/src/gen_impl.rs @@ -54,6 +54,7 @@ impl Gn { impl Gn { /// create a new generator with default stack size #[cfg_attr(feature = "cargo-clippy", allow(clippy::new_ret_no_self))] + #[deprecated(since = "0.6.18", note = "please use `scope` version instead")] pub fn new<'a, T: Any, F>(f: F) -> Generator<'a, A, T> where F: FnOnce() -> T + 'a, @@ -62,6 +63,7 @@ impl Gn { } /// create a new generator with specified stack size + #[deprecated(since = "0.6.18", note = "please use `scope` version instead")] pub fn new_opt<'a, T: Any, F>(size: usize, f: F) -> Generator<'a, A, T> where F: FnOnce() -> T + 'a, @@ -88,8 +90,10 @@ pub struct GeneratorImpl<'a, A, T> { impl<'a, A: Any, T: Any> GeneratorImpl<'a, A, T> { /// create a new generator with default stack size pub fn init_context(&mut self) { - self.context.para = &mut self.para as &mut dyn Any; - self.context.ret = &mut self.ret as &mut dyn Any; + unsafe { + *self.context.para.as_mut_ptr() = &mut self.para as &mut dyn Any; + *self.context.ret.as_mut_ptr() = &mut self.ret as &mut dyn Any; + } } } @@ -353,6 +357,7 @@ impl<'a, T> Iterator for GeneratorImpl<'a, (), T> { impl<'a, A, T> fmt::Debug for GeneratorImpl<'a, A, T> { #[cfg(nightly)] + #[allow(unused_unsafe)] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use std::intrinsics::type_name; write!( diff --git a/src/lib.rs b/src/lib.rs index b2caec8..09018a4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,7 @@ #![cfg_attr(nightly, feature(thread_local))] // #![cfg_attr(test, deny(warnings))] #![deny(missing_docs)] +#![allow(deprecated)] #[macro_use] extern crate log; diff --git a/src/rt.rs b/src/rt.rs index 765227d..4509d67 100644 --- a/src/rt.rs +++ b/src/rt.rs @@ -3,7 +3,7 @@ //! generator run time context management //! use std::any::Any; -use std::mem; +use std::mem::MaybeUninit; use std::ptr; use crate::reg_context::RegContext; @@ -48,9 +48,9 @@ pub struct Context { /// generator execution stack pub stack: Stack, /// passed in para for send - pub para: *mut dyn Any, + pub para: MaybeUninit<*mut dyn Any>, /// this is just a buffer for the return value - pub ret: *mut dyn Any, + pub ret: MaybeUninit<*mut dyn Any>, /// track generator ref, yield will -1, send will +1 pub _ref: u32, /// propagate panic @@ -70,8 +70,8 @@ impl Context { Context { regs: RegContext::empty(), stack: Stack::empty(), - para: unsafe { mem::MaybeUninit::uninit().assume_init() }, - ret: unsafe { mem::MaybeUninit::uninit().assume_init() }, + para: MaybeUninit::zeroed(), + ret: MaybeUninit::zeroed(), _ref: 1, // none zero means it's not running err: None, child: ptr::null_mut(), @@ -85,8 +85,8 @@ impl Context { Context { regs: RegContext::empty(), stack: Stack::new(size), - para: unsafe { mem::MaybeUninit::uninit().assume_init() }, - ret: unsafe { mem::MaybeUninit::uninit().assume_init() }, + para: MaybeUninit::zeroed(), + ret: MaybeUninit::zeroed(), _ref: 1, // none zero means it's not running err: None, child: ptr::null_mut(), @@ -103,11 +103,15 @@ impl Context { /// get current generator send para #[inline] - pub fn get_para(&self) -> Option + pub fn get_para(&mut self) -> Option where A: Any, { - let para = unsafe { &mut *self.para }; + let para = unsafe { + let para_ptr = *self.para.as_mut_ptr(); + assert!(!para_ptr.is_null()); + &mut *para_ptr + }; match para.downcast_mut::>() { Some(v) => v.take(), #[cold] @@ -117,8 +121,12 @@ impl Context { /// get coroutine send para #[inline] - pub fn co_get_para(&self) -> Option { - let para = unsafe { &mut *(self.para as *mut Option) }; + pub fn co_get_para(&mut self) -> Option { + let para = unsafe { + let para_ptr = *self.para.as_mut_ptr(); + debug_assert!(!para_ptr.is_null()); + &mut *(para_ptr as *mut Option) + }; para.take() } @@ -139,8 +147,12 @@ impl Context { /// set coroutine send para /// without check the data type for coroutine performance reason #[inline] - pub fn co_set_para(&self, data: A) { - let para = unsafe { &mut *(self.para as *mut Option) }; + pub fn co_set_para(&mut self, data: A) { + let para = unsafe { + let para_ptr = *self.para.as_mut_ptr(); + debug_assert!(!para_ptr.is_null()); + &mut *(para_ptr as *mut Option) + }; *para = Some(data); } @@ -150,7 +162,11 @@ impl Context { where T: Any, { - let ret = unsafe { &mut *self.ret }; + let ret = unsafe { + let ret_ptr = *self.ret.as_mut_ptr(); + assert!(!ret_ptr.is_null()); + &mut *ret_ptr + }; match ret.downcast_mut::>() { Some(r) => *r = Some(v), #[cold] @@ -162,7 +178,11 @@ impl Context { /// without check the data type for coroutine performance reason #[inline] pub fn co_set_ret(&mut self, v: T) { - let ret = unsafe { &mut *(self.ret as *mut Option) }; + let ret = unsafe { + let ret_ptr = *self.ret.as_mut_ptr(); + debug_assert!(!ret_ptr.is_null()); + &mut *(ret_ptr as *mut Option) + }; *ret = Some(v); } } @@ -263,6 +283,7 @@ impl ContextStack { #[inline] fn type_error(msg: &str) -> ! { #[cfg(nightly)] + #[allow(unused_unsafe)] { use std::intrinsics::type_name; let t = unsafe { type_name::() }; diff --git a/src/yield_.rs b/src/yield_.rs index 75936bc..7e22aec 100644 --- a/src/yield_.rs +++ b/src/yield_.rs @@ -64,7 +64,7 @@ fn raw_yield(env: &ContextStack, context: &mut Context, v: T) { /// yield something without catch passed in para #[inline] -// #[deprecated(since="0.5.0", note="please use `scope` instead")] +#[deprecated(since = "0.6.18", note = "please use `scope` version instead")] pub fn yield_with(v: T) { let env = ContextStack::current(); let context = env.top(); @@ -73,7 +73,7 @@ pub fn yield_with(v: T) { /// get the passed in para #[inline] -// #[deprecated(since="0.5.0", note="please use `scope` instead")] +#[deprecated(since = "0.6.18", note = "please use `scope` version instead")] pub fn get_yield() -> Option { let context = ContextStack::current().top(); raw_get_yield(context) @@ -99,7 +99,7 @@ fn raw_get_yield(context: &mut Context) -> Option { // this is fine, but it's totally safe that we can refer to the function block // since we will come back later #[inline] -// #[deprecated(since="0.5.0", note="please use `scope` instead")] +#[deprecated(since = "0.6.18", note = "please use `scope` version instead")] pub fn yield_(v: T) -> Option { let env = ContextStack::current(); let context = env.top(); @@ -108,7 +108,7 @@ pub fn yield_(v: T) -> Option { } /// `yield_from` -// #[deprecated(since="0.5.0", note="please use `scope` instead")] +#[deprecated(since = "0.6.18", note = "please use `scope` version instead")] pub fn yield_from(mut g: Generator) -> Option { let env = ContextStack::current(); let context = env.top(); diff --git a/tests/lib.rs b/tests/lib.rs index 3bbacc7..cc21c91 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -1,3 +1,5 @@ +#![allow(deprecated)] + extern crate generator; use generator::*; @@ -480,3 +482,14 @@ fn test_re_init() { fn done_in_normal() { done!(); } + +#[test] +#[should_panic] +fn invaild_yield_in_scope() { + let g = Gn::new_scoped(|_| { + // invalid use raw yield API with scope + yield_::(()); + }); + + for () in g {} +}