From 1fe8dcd7a9896e06338fda2e31bd0425773f0b64 Mon Sep 17 00:00:00 2001 From: J Claire Date: Wed, 18 Sep 2019 17:02:46 -0400 Subject: [PATCH 01/10] Test case `non_send_item` added. --- rayon-futures/src/test.rs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/rayon-futures/src/test.rs b/rayon-futures/src/test.rs index 32a0011e9..294607b6e 100644 --- a/rayon-futures/src/test.rs +++ b/rayon-futures/src/test.rs @@ -286,3 +286,42 @@ fn async_future_scope_interact() { assert_eq!(vec![44], vec); } + +#[test] +fn non_send_item() { + use std::marker::PhantomData; + use std::thread; + use futures::future::{poll_fn, PollFn}; + + struct TattleTale { + id: thread::ThreadId, + not_send: PhantomData<*mut ()> + } + + impl Drop for TattleTale { + fn drop(&mut self) { + let drop_id = thread::current().id(); + assert_eq!(self.id, drop_id); + } + } + + let evil_future_factory = || { poll_fn(|| { + let evil_item = TattleTale { + id: thread::current().id(), + not_send: PhantomData, + }; + return Ok(Async::Ready(evil_item)); + } ) }; + + let pool = ThreadPool::global(); + + scope(|s| { + let futures: Vec<_> = (0..1000) + .map(|_: i32| s.spawn_future(evil_future_factory())) + .collect(); + + for f in futures { + let _: Result<_, ()> = f.rayon_wait(); + } + } ); +} From b66e8041c65bdc3c5f5ea7fdff49366c186a95ea Mon Sep 17 00:00:00 2001 From: J Claire Date: Wed, 18 Sep 2019 18:15:08 -0400 Subject: [PATCH 02/10] Fix. Passes all tests but `non_send_item` needs to become a compile-fail test. --- rayon-futures/src/lib.rs | 67 +++++++++++++++++++++++++++++++++++---- rayon-futures/src/test.rs | 2 +- 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/rayon-futures/src/lib.rs b/rayon-futures/src/lib.rs index 040134e5e..22eada9b4 100644 --- a/rayon-futures/src/lib.rs +++ b/rayon-futures/src/lib.rs @@ -34,7 +34,9 @@ const STATE_COMPLETE: usize = 4; pub trait ScopeFutureExt<'scope> { fn spawn_future(&self, future: F) -> RayonFuture where - F: Future + Send + 'scope; + F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send; } impl<'scope, T> ScopeFutureExt<'scope> for T @@ -44,6 +46,8 @@ where fn spawn_future(&self, future: F) -> RayonFuture where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send { let inner = ScopeFuture::spawn(future, self.to_scope_handle()); @@ -136,6 +140,8 @@ impl fmt::Debug for RayonFuture { struct ScopeFuture<'scope, F, S> where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { state: AtomicUsize, @@ -149,6 +155,8 @@ type CUError = as Future>::Error; struct ScopeFutureContents<'scope, F, S> where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { spawn: Option>>, @@ -160,7 +168,7 @@ where // the counter in the scope; since the scope doesn't terminate until // counter reaches zero, and we hold a ref in this counter, we are // assured that this pointer remains valid - scope: Option, + scope: Option>, waiting_task: Option, result: Poll, CUError>, @@ -171,6 +179,8 @@ where impl<'scope, F, S> fmt::Debug for ScopeFutureContents<'scope, F, S> where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { @@ -183,11 +193,15 @@ where struct ArcScopeFuture<'scope, F, S>(Arc>) where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>; impl<'scope, F, S> Clone for ArcScopeFuture<'scope, F, S> where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { fn clone(&self) -> Self { @@ -198,6 +212,8 @@ where impl<'scope, F, S> Notify for ArcScopeFuture<'scope, F, S> where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { fn notify(&self, id: usize) { @@ -225,6 +241,8 @@ unsafe impl<'scope, F, S> Sync for ScopeFutureWrapped<'scope, F, S> {} impl<'scope, F, S> Notify for ScopeFutureWrapped<'scope, F, S> where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { fn notify(&self, id: usize) { @@ -264,6 +282,8 @@ where unsafe impl<'scope, F, S> UnsafeNotify for ScopeFutureWrapped<'scope, F, S> where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { unsafe fn clone_raw(&self) -> NotifyHandle { @@ -285,6 +305,8 @@ where impl<'scope, F, S> From> for NotifyHandle where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { fn from(rc: ArcScopeFuture<'scope, F, S>) -> NotifyHandle { @@ -309,7 +331,30 @@ where } // Assert that the `*const` is safe to transmit between threads: -unsafe impl<'scope, F, S> Send for ScopeFuture<'scope, F, S> +struct ScopeHandleSend<'s, S: ScopeHandle<'s>>(S, PhantomData<&'s ()>); +unsafe impl<'scope, S> Send for ScopeHandleSend<'scope, S> +where + S: ScopeHandle<'scope> +{ +} +impl<'scope, S> ScopeHandleSend<'scope, S> +where + S: ScopeHandle<'scope> +{ + unsafe fn assert_send(s: S) -> Self { + ScopeHandleSend(s, PhantomData) + } + unsafe fn spawn_task(&self, task: Arc) { + self.0.spawn_task(task); + } + fn panicked(self, err: Box) { + self.0.panicked(err); + } + fn ok(self) { + self.0.ok(); + } +} +/* unsafe impl<'scope, F, S> Send for ScopeFuture<'scope, F, S> where F: Future + Send + 'scope, S: ScopeHandle<'scope>, @@ -320,11 +365,13 @@ where F: Future + Send + 'scope, S: ScopeHandle<'scope>, { -} +} */ impl<'scope, F, S> ScopeFuture<'scope, F, S> where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { fn spawn(future: F, scope: S) -> Arc { @@ -338,7 +385,7 @@ where contents: Mutex::new(ScopeFutureContents { spawn: None, this: None, - scope: Some(scope), + scope: unsafe { Some(ScopeHandleSend::assert_send(scope)) }, waiting_task: None, result: Ok(Async::NotReady), canceled: false, @@ -466,6 +513,8 @@ where impl<'scope, F, S> Notify for ScopeFuture<'scope, F, S> where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { fn notify(&self, _: usize) { @@ -476,6 +525,8 @@ where impl<'scope, F, S> RayonTask for ScopeFuture<'scope, F, S> where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { fn execute(this: Arc) { @@ -510,6 +561,8 @@ where impl<'scope, F, S> ScopeFutureContents<'scope, F, S> where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { fn poll(&mut self) -> Poll, CUError> { @@ -578,7 +631,9 @@ trait ScopeFutureTrait: Send + Sync { impl<'scope, F, S> ScopeFutureTrait, CUError> for ScopeFuture<'scope, F, S> where - F: Future + Send, + F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { fn probe(&self) -> bool { diff --git a/rayon-futures/src/test.rs b/rayon-futures/src/test.rs index 294607b6e..49d63effc 100644 --- a/rayon-futures/src/test.rs +++ b/rayon-futures/src/test.rs @@ -291,7 +291,7 @@ fn async_future_scope_interact() { fn non_send_item() { use std::marker::PhantomData; use std::thread; - use futures::future::{poll_fn, PollFn}; + use futures::future::poll_fn; struct TattleTale { id: thread::ThreadId, From a4b89bb9b80385d9692df03ed0cea499afc39eaa Mon Sep 17 00:00:00 2001 From: J Claire Date: Wed, 18 Sep 2019 18:38:13 -0400 Subject: [PATCH 03/10] Not having luck with the doctest. --- rayon-futures/src/compile_fail/mod.rs | 1 + .../src/compile_fail/non_send_item.rs | 18 ++++++++++++++++++ rayon-futures/src/test.rs | 4 ++-- 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 rayon-futures/src/compile_fail/non_send_item.rs diff --git a/rayon-futures/src/compile_fail/mod.rs b/rayon-futures/src/compile_fail/mod.rs index 9e08a7bd2..8ee424601 100644 --- a/rayon-futures/src/compile_fail/mod.rs +++ b/rayon-futures/src/compile_fail/mod.rs @@ -1,2 +1,3 @@ // These modules contain `compile_fail` doc tests. mod future_escape; +mod non_send_item; diff --git a/rayon-futures/src/compile_fail/non_send_item.rs b/rayon-futures/src/compile_fail/non_send_item.rs new file mode 100644 index 000000000..40a8e2c39 --- /dev/null +++ b/rayon-futures/src/compile_fail/non_send_item.rs @@ -0,0 +1,18 @@ +/*! ``` +use std::marker::PhantomData; +use futures::future::poll_fn; +use futures::Poll; +use futures::Async; +use futures::Future; +use rayon_futures::ScopeFutureExt; +use rayon_core::scope; +use rayon_core::ThreadPool; + +let evil_future = poll_fn(|| Ok(Async::Ready(PhantomData::<*mut ()>)) ); +let pool = ThreadPool::global(); + +scope(|s| { + let f = s.spawn_future(evil_future); + let _: Result<_, ()> = f.rayon_waist(); +} ); +*/ diff --git a/rayon-futures/src/test.rs b/rayon-futures/src/test.rs index 49d63effc..6b0b8dbe7 100644 --- a/rayon-futures/src/test.rs +++ b/rayon-futures/src/test.rs @@ -287,7 +287,7 @@ fn async_future_scope_interact() { assert_eq!(vec![44], vec); } -#[test] +/* #[test] fn non_send_item() { use std::marker::PhantomData; use std::thread; @@ -324,4 +324,4 @@ fn non_send_item() { let _: Result<_, ()> = f.rayon_wait(); } } ); -} +} */ From b4b81094de48d433d5bbab6b7c3206445ac56bef Mon Sep 17 00:00:00 2001 From: J Claire Date: Wed, 18 Sep 2019 18:48:38 -0400 Subject: [PATCH 04/10] Missing tri-ticks --- rayon-futures/src/compile_fail/non_send_item.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rayon-futures/src/compile_fail/non_send_item.rs b/rayon-futures/src/compile_fail/non_send_item.rs index 40a8e2c39..359b66313 100644 --- a/rayon-futures/src/compile_fail/non_send_item.rs +++ b/rayon-futures/src/compile_fail/non_send_item.rs @@ -15,4 +15,4 @@ scope(|s| { let f = s.spawn_future(evil_future); let _: Result<_, ()> = f.rayon_waist(); } ); -*/ +``` */ From 3a7b2d89ef9df3bf254658ff14822077d9e39f2f Mon Sep 17 00:00:00 2001 From: J Claire Date: Wed, 18 Sep 2019 19:19:23 -0400 Subject: [PATCH 05/10] Remove commented-out unsafe impl. --- rayon-futures/src/lib.rs | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/rayon-futures/src/lib.rs b/rayon-futures/src/lib.rs index 22eada9b4..dbc719b14 100644 --- a/rayon-futures/src/lib.rs +++ b/rayon-futures/src/lib.rs @@ -335,8 +335,7 @@ struct ScopeHandleSend<'s, S: ScopeHandle<'s>>(S, PhantomData<&'s ()>); unsafe impl<'scope, S> Send for ScopeHandleSend<'scope, S> where S: ScopeHandle<'scope> -{ -} +{} impl<'scope, S> ScopeHandleSend<'scope, S> where S: ScopeHandle<'scope> @@ -354,18 +353,6 @@ where self.0.ok(); } } -/* unsafe impl<'scope, F, S> Send for ScopeFuture<'scope, F, S> -where - F: Future + Send + 'scope, - S: ScopeHandle<'scope>, -{ -} -unsafe impl<'scope, F, S> Sync for ScopeFuture<'scope, F, S> -where - F: Future + Send + 'scope, - S: ScopeHandle<'scope>, -{ -} */ impl<'scope, F, S> ScopeFuture<'scope, F, S> where From 7d22a13e58ebda2ff69e8a003e81c71698524ea8 Mon Sep 17 00:00:00 2001 From: J Claire Date: Wed, 18 Sep 2019 19:21:42 -0400 Subject: [PATCH 06/10] cargo fmt --- rayon-futures/src/lib.rs | 11 ++++------- rayon-futures/src/test.rs | 4 ++-- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/rayon-futures/src/lib.rs b/rayon-futures/src/lib.rs index dbc719b14..78a54b179 100644 --- a/rayon-futures/src/lib.rs +++ b/rayon-futures/src/lib.rs @@ -47,7 +47,7 @@ where where F: Future + Send + 'scope, ::Item: Send, - ::Error: Send + ::Error: Send, { let inner = ScopeFuture::spawn(future, self.to_scope_handle()); @@ -332,13 +332,10 @@ where // Assert that the `*const` is safe to transmit between threads: struct ScopeHandleSend<'s, S: ScopeHandle<'s>>(S, PhantomData<&'s ()>); -unsafe impl<'scope, S> Send for ScopeHandleSend<'scope, S> +unsafe impl<'scope, S> Send for ScopeHandleSend<'scope, S> where S: ScopeHandle<'scope> {} +impl<'scope, S> ScopeHandleSend<'scope, S> where - S: ScopeHandle<'scope> -{} -impl<'scope, S> ScopeHandleSend<'scope, S> -where - S: ScopeHandle<'scope> + S: ScopeHandle<'scope>, { unsafe fn assert_send(s: S) -> Self { ScopeHandleSend(s, PhantomData) diff --git a/rayon-futures/src/test.rs b/rayon-futures/src/test.rs index 6b0b8dbe7..50a5f9767 100644 --- a/rayon-futures/src/test.rs +++ b/rayon-futures/src/test.rs @@ -292,7 +292,7 @@ fn non_send_item() { use std::marker::PhantomData; use std::thread; use futures::future::poll_fn; - + struct TattleTale { id: thread::ThreadId, not_send: PhantomData<*mut ()> @@ -319,7 +319,7 @@ fn non_send_item() { let futures: Vec<_> = (0..1000) .map(|_: i32| s.spawn_future(evil_future_factory())) .collect(); - + for f in futures { let _: Result<_, ()> = f.rayon_wait(); } From 22df154d2b3e1cfb4ec98e5eded90bd3e2270b92 Mon Sep 17 00:00:00 2001 From: J Claire Date: Wed, 18 Sep 2019 18:15:08 -0400 Subject: [PATCH 07/10] Fixed and tested issue 697. Futures that return `!Send` values are now rejected by a compiler error. `Sync` and `Send` are now derived by the compiler for `ScopeFuture`, except that the `Send`-safety of `impl ScopeHandle` is is still asserted unsafety. I did not review `rayon_core` to judge whether that is correct. --- rayon-futures/src/compile_fail/mod.rs | 1 + .../src/compile_fail/non_send_item.rs | 62 ++++++++++++++++++ rayon-futures/src/lib.rs | 63 +++++++++++++++---- rayon-futures/src/test.rs | 39 ------------ 4 files changed, 114 insertions(+), 51 deletions(-) create mode 100644 rayon-futures/src/compile_fail/non_send_item.rs diff --git a/rayon-futures/src/compile_fail/mod.rs b/rayon-futures/src/compile_fail/mod.rs index 9e08a7bd2..8ee424601 100644 --- a/rayon-futures/src/compile_fail/mod.rs +++ b/rayon-futures/src/compile_fail/mod.rs @@ -1,2 +1,3 @@ // These modules contain `compile_fail` doc tests. mod future_escape; +mod non_send_item; diff --git a/rayon-futures/src/compile_fail/non_send_item.rs b/rayon-futures/src/compile_fail/non_send_item.rs new file mode 100644 index 000000000..474404940 --- /dev/null +++ b/rayon-futures/src/compile_fail/non_send_item.rs @@ -0,0 +1,62 @@ +/*! ```compile_fail,E0277 +extern crate futures; +extern crate rayon_core; + +use std::marker::PhantomData; +use futures::future::poll_fn; +use futures::Poll; +use futures::Async; +use futures::Future; +use rayon_futures::ScopeFutureExt; +use rayon_core::scope; +use rayon_core::ThreadPool; + +let evil_future = poll_fn(|| Ok(Async::Ready(PhantomData::<*mut ()>)) ); +let pool = ThreadPool::global(); + +scope(|s| { + let f = s.spawn_future(evil_future); //~ ERROR + let _: Result<_, ()> = f.rayon_wait(); +} ); +``` */ + +// Original test case: + +/* #[test] +fn non_send_item() { + use std::marker::PhantomData; + use std::thread; + use futures::future::poll_fn; + + struct TattleTale { + id: thread::ThreadId, + not_send: PhantomData<*mut ()> + } + + impl Drop for TattleTale { + fn drop(&mut self) { + let drop_id = thread::current().id(); + assert_eq!(self.id, drop_id); + } + } + + let evil_future_factory = || { poll_fn(|| { + let evil_item = TattleTale { + id: thread::current().id(), + not_send: PhantomData, + }; + return Ok(Async::Ready(evil_item)); + } ) }; + + let pool = ThreadPool::global(); + + scope(|s| { + let futures: Vec<_> = (0..1000) + .map(|_: i32| s.spawn_future(evil_future_factory())) + .collect(); + + for f in futures { + let _: Result<_, ()> = f.rayon_wait(); + } + } ); +} */ diff --git a/rayon-futures/src/lib.rs b/rayon-futures/src/lib.rs index 040134e5e..78a54b179 100644 --- a/rayon-futures/src/lib.rs +++ b/rayon-futures/src/lib.rs @@ -34,7 +34,9 @@ const STATE_COMPLETE: usize = 4; pub trait ScopeFutureExt<'scope> { fn spawn_future(&self, future: F) -> RayonFuture where - F: Future + Send + 'scope; + F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send; } impl<'scope, T> ScopeFutureExt<'scope> for T @@ -44,6 +46,8 @@ where fn spawn_future(&self, future: F) -> RayonFuture where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, { let inner = ScopeFuture::spawn(future, self.to_scope_handle()); @@ -136,6 +140,8 @@ impl fmt::Debug for RayonFuture { struct ScopeFuture<'scope, F, S> where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { state: AtomicUsize, @@ -149,6 +155,8 @@ type CUError = as Future>::Error; struct ScopeFutureContents<'scope, F, S> where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { spawn: Option>>, @@ -160,7 +168,7 @@ where // the counter in the scope; since the scope doesn't terminate until // counter reaches zero, and we hold a ref in this counter, we are // assured that this pointer remains valid - scope: Option, + scope: Option>, waiting_task: Option, result: Poll, CUError>, @@ -171,6 +179,8 @@ where impl<'scope, F, S> fmt::Debug for ScopeFutureContents<'scope, F, S> where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { @@ -183,11 +193,15 @@ where struct ArcScopeFuture<'scope, F, S>(Arc>) where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>; impl<'scope, F, S> Clone for ArcScopeFuture<'scope, F, S> where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { fn clone(&self) -> Self { @@ -198,6 +212,8 @@ where impl<'scope, F, S> Notify for ArcScopeFuture<'scope, F, S> where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { fn notify(&self, id: usize) { @@ -225,6 +241,8 @@ unsafe impl<'scope, F, S> Sync for ScopeFutureWrapped<'scope, F, S> {} impl<'scope, F, S> Notify for ScopeFutureWrapped<'scope, F, S> where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { fn notify(&self, id: usize) { @@ -264,6 +282,8 @@ where unsafe impl<'scope, F, S> UnsafeNotify for ScopeFutureWrapped<'scope, F, S> where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { unsafe fn clone_raw(&self) -> NotifyHandle { @@ -285,6 +305,8 @@ where impl<'scope, F, S> From> for NotifyHandle where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { fn from(rc: ArcScopeFuture<'scope, F, S>) -> NotifyHandle { @@ -309,22 +331,31 @@ where } // Assert that the `*const` is safe to transmit between threads: -unsafe impl<'scope, F, S> Send for ScopeFuture<'scope, F, S> -where - F: Future + Send + 'scope, - S: ScopeHandle<'scope>, -{ -} -unsafe impl<'scope, F, S> Sync for ScopeFuture<'scope, F, S> +struct ScopeHandleSend<'s, S: ScopeHandle<'s>>(S, PhantomData<&'s ()>); +unsafe impl<'scope, S> Send for ScopeHandleSend<'scope, S> where S: ScopeHandle<'scope> {} +impl<'scope, S> ScopeHandleSend<'scope, S> where - F: Future + Send + 'scope, S: ScopeHandle<'scope>, { + unsafe fn assert_send(s: S) -> Self { + ScopeHandleSend(s, PhantomData) + } + unsafe fn spawn_task(&self, task: Arc) { + self.0.spawn_task(task); + } + fn panicked(self, err: Box) { + self.0.panicked(err); + } + fn ok(self) { + self.0.ok(); + } } impl<'scope, F, S> ScopeFuture<'scope, F, S> where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { fn spawn(future: F, scope: S) -> Arc { @@ -338,7 +369,7 @@ where contents: Mutex::new(ScopeFutureContents { spawn: None, this: None, - scope: Some(scope), + scope: unsafe { Some(ScopeHandleSend::assert_send(scope)) }, waiting_task: None, result: Ok(Async::NotReady), canceled: false, @@ -466,6 +497,8 @@ where impl<'scope, F, S> Notify for ScopeFuture<'scope, F, S> where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { fn notify(&self, _: usize) { @@ -476,6 +509,8 @@ where impl<'scope, F, S> RayonTask for ScopeFuture<'scope, F, S> where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { fn execute(this: Arc) { @@ -510,6 +545,8 @@ where impl<'scope, F, S> ScopeFutureContents<'scope, F, S> where F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { fn poll(&mut self) -> Poll, CUError> { @@ -578,7 +615,9 @@ trait ScopeFutureTrait: Send + Sync { impl<'scope, F, S> ScopeFutureTrait, CUError> for ScopeFuture<'scope, F, S> where - F: Future + Send, + F: Future + Send + 'scope, + ::Item: Send, + ::Error: Send, S: ScopeHandle<'scope>, { fn probe(&self) -> bool { diff --git a/rayon-futures/src/test.rs b/rayon-futures/src/test.rs index 294607b6e..32a0011e9 100644 --- a/rayon-futures/src/test.rs +++ b/rayon-futures/src/test.rs @@ -286,42 +286,3 @@ fn async_future_scope_interact() { assert_eq!(vec![44], vec); } - -#[test] -fn non_send_item() { - use std::marker::PhantomData; - use std::thread; - use futures::future::{poll_fn, PollFn}; - - struct TattleTale { - id: thread::ThreadId, - not_send: PhantomData<*mut ()> - } - - impl Drop for TattleTale { - fn drop(&mut self) { - let drop_id = thread::current().id(); - assert_eq!(self.id, drop_id); - } - } - - let evil_future_factory = || { poll_fn(|| { - let evil_item = TattleTale { - id: thread::current().id(), - not_send: PhantomData, - }; - return Ok(Async::Ready(evil_item)); - } ) }; - - let pool = ThreadPool::global(); - - scope(|s| { - let futures: Vec<_> = (0..1000) - .map(|_: i32| s.spawn_future(evil_future_factory())) - .collect(); - - for f in futures { - let _: Result<_, ()> = f.rayon_wait(); - } - } ); -} From 49a39a8bf129013cfab8cd17770d60e72a6fffb9 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 19 Dec 2019 10:25:26 -0800 Subject: [PATCH 08/10] Release and deprecate rayon-futures 0.1.1 --- RELEASES.md | 21 +++++++++++++++++++++ ci/compat-Cargo.lock | 2 +- rayon-futures/Cargo.toml | 9 ++++++--- rayon-futures/README.md | 4 ++++ 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 515e817b3..45073350f 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,24 @@ +# Release rayon-futures 0.1.1 (2019-12-20) + +- `Send` bounds have been added for the `Item` and `Error` associated types on + all generic `F: Future` interfaces. While technically a breaking change, this + is a soundness fix, so we are not increasing the semantic version for this. +- This crate is now deprecated, and the `--cfg=rayon_unstable` supporting code + will be removed in `rayon-core 1.7.0`. This only supported the now-obsolete + `Future` from `futures 0.1`, while support for `std::future::Future` is + expected to come directly in `rayon-core` -- although that is not ready yet. + +## Contributors + +Thanks to all of the contributors for this release! + +- @cuviper +- @kornelski +- @jClaireCodesStuff +- @jwass +- @seanchen1991 + + # Release rayon 1.2.1 / rayon-core 1.6.1 (2019-11-20) - Update crossbeam dependencies. diff --git a/ci/compat-Cargo.lock b/ci/compat-Cargo.lock index 4d2e1f018..ed2d9f36d 100644 --- a/ci/compat-Cargo.lock +++ b/ci/compat-Cargo.lock @@ -840,7 +840,7 @@ dependencies = [ [[package]] name = "rayon-futures" -version = "0.1.0" +version = "0.1.1" dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "rayon-core 1.6.1", diff --git a/rayon-futures/Cargo.toml b/rayon-futures/Cargo.toml index 4522b2e0b..f36ba86b1 100644 --- a/rayon-futures/Cargo.toml +++ b/rayon-futures/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "rayon-futures" -version = "0.1.0" # reminder to update html_root_url attribute +version = "0.1.1" # reminder to update html_root_url attribute authors = ["Niko Matsakis ", "Josh Stone "] -description = "Futures integration into Rayon" +description = "(deprecated) Futures integration into Rayon" license = "Apache-2.0/MIT" repository = "https://github.com/rayon-rs/rayon" documentation = "https://docs.rs/rayon-futures/" @@ -12,5 +12,8 @@ keywords = ["parallel", "thread", "concurrency", "join", "performance"] categories = ["concurrency"] [dependencies] -rayon-core = { version = "1.3", path = "../rayon-core" } +rayon-core = { version = "~1.6", path = "../rayon-core" } futures = "0.1.16" + +[badges] +maintenance = { status = "deprecated" } diff --git a/rayon-futures/README.md b/rayon-futures/README.md index f595a5b6b..e358488f7 100644 --- a/rayon-futures/README.md +++ b/rayon-futures/README.md @@ -1,5 +1,9 @@ # Future integration into Rayon +This crate is now **deprecated**, because it only supports the obsolete +`futures-0.1`. New integration with `std::future::Future` will likely +take place directly in `rayon-core`, but this is left to the ... future. + **NOTE:** `rayon-futures` currently requires unstable features of `rayon-core`, which may only be enabled with `rustc --cfg`, e.g. by setting `RUSTFLAGS=--cfg rayon_unstable` in the environment. From 9dcf68e9ca3bee6991b4179e0c98316537b5655f Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 19 Dec 2019 12:47:27 -0800 Subject: [PATCH 09/10] Include rayon-futures-0.1.x in CI --- .travis.yml | 1 + appveyor.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 5991f7a76..6da5eb013 100644 --- a/.travis.yml +++ b/.travis.yml @@ -94,6 +94,7 @@ script: branches: only: + - rayon-futures-0.1.x - master - staging - trying diff --git a/appveyor.yml b/appveyor.yml index a223c7e6f..f6dd4835f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -36,6 +36,7 @@ test_script: branches: only: + - rayon-futures-0.1.x - master - staging - trying From 30c50dead34373f6eefc1788d70adc8a6486030b Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Sat, 21 Dec 2019 06:56:17 -0800 Subject: [PATCH 10/10] bump the release date --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 45073350f..2009f7e77 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,4 +1,4 @@ -# Release rayon-futures 0.1.1 (2019-12-20) +# Release rayon-futures 0.1.1 (2019-12-21) - `Send` bounds have been added for the `Item` and `Error` associated types on all generic `F: Future` interfaces. While technically a breaking change, this