From 1fe8dcd7a9896e06338fda2e31bd0425773f0b64 Mon Sep 17 00:00:00 2001 From: J Claire Date: Wed, 18 Sep 2019 17:02:46 -0400 Subject: [PATCH 1/7] 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 2/7] 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 3/7] 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 4/7] 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 5/7] 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 6/7] 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 7/7] 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(); - } - } ); -}