From 3d43f828f5f1261b88f00582074f6cd021f31614 Mon Sep 17 00:00:00 2001 From: Josef Reinhard Brandl Date: Sat, 30 Jun 2018 17:26:38 +0200 Subject: [PATCH 01/11] Make custom trait object for `Future` generic --- src/liballoc/boxed.rs | 30 +++---- src/libcore/task/executor.rs | 8 +- src/libcore/task/{task.rs => future_obj.rs} | 99 +++++++++++---------- src/libcore/task/mod.rs | 4 +- src/test/run-pass/async-await.rs | 4 +- src/test/run-pass/futures-api.rs | 4 +- 6 files changed, 77 insertions(+), 72 deletions(-) rename src/libcore/task/{task.rs => future_obj.rs} (50%) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 6a05ef680889a..c1778ef101ac6 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -66,7 +66,7 @@ use core::marker::{Unpin, Unsize}; use core::mem::{self, PinMut}; use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState}; use core::ptr::{self, NonNull, Unique}; -use core::task::{Context, Poll, UnsafeTask, TaskObj, LocalTaskObj}; +use core::task::{Context, Poll, UnsafeFutureObj, FutureObj, LocalFutureObj}; use core::convert::From; use raw_vec::RawVec; @@ -933,12 +933,12 @@ impl<'a, F: ?Sized + Future> Future for PinBox { } #[unstable(feature = "futures_api", issue = "50547")] -unsafe impl + 'static> UnsafeTask for PinBox { +unsafe impl + 'static> UnsafeFutureObj for PinBox { fn into_raw(self) -> *mut () { PinBox::into_raw(self) as *mut () } - unsafe fn poll(task: *mut (), cx: &mut Context) -> Poll<()> { + unsafe fn poll(task: *mut (), cx: &mut Context) -> Poll { let ptr = task as *mut F; let pin: PinMut = PinMut::new_unchecked(&mut *ptr); pin.poll(cx) @@ -950,29 +950,29 @@ unsafe impl + 'static> UnsafeTask for PinBox { } #[unstable(feature = "futures_api", issue = "50547")] -impl + Send + 'static> From> for TaskObj { - fn from(boxed: PinBox) -> Self { - TaskObj::new(boxed) +impl + Send + 'static> Into> for PinBox { + fn into(self) -> FutureObj { + FutureObj::new(self) } } #[unstable(feature = "futures_api", issue = "50547")] -impl + Send + 'static> From> for TaskObj { - fn from(boxed: Box) -> Self { - TaskObj::new(PinBox::from(boxed)) +impl + Send + 'static> Into> for Box { + fn into(self) -> FutureObj { + FutureObj::new(PinBox::from(self)) } } #[unstable(feature = "futures_api", issue = "50547")] -impl + 'static> From> for LocalTaskObj { - fn from(boxed: PinBox) -> Self { - LocalTaskObj::new(boxed) +impl + 'static> Into> for PinBox { + fn into(self) -> LocalFutureObj { + LocalFutureObj::new(self) } } #[unstable(feature = "futures_api", issue = "50547")] -impl + 'static> From> for LocalTaskObj { - fn from(boxed: Box) -> Self { - LocalTaskObj::new(PinBox::from(boxed)) +impl + 'static> Into> for Box { + fn into(self) -> LocalFutureObj { + LocalFutureObj::new(PinBox::from(self)) } } diff --git a/src/libcore/task/executor.rs b/src/libcore/task/executor.rs index 73bf80d2f9997..55ea5e724c1cc 100644 --- a/src/libcore/task/executor.rs +++ b/src/libcore/task/executor.rs @@ -13,7 +13,7 @@ issue = "50547")] use fmt; -use super::{TaskObj, LocalTaskObj}; +use super::{FutureObj, LocalFutureObj}; /// A task executor. /// @@ -29,7 +29,7 @@ pub trait Executor { /// /// The executor may be unable to spawn tasks, either because it has /// been shut down or is resource-constrained. - fn spawn_obj(&mut self, task: TaskObj) -> Result<(), SpawnObjError>; + fn spawn_obj(&mut self, task: FutureObj<()>) -> Result<(), SpawnObjError>; /// Determine whether the executor is able to spawn new tasks. /// @@ -76,7 +76,7 @@ pub struct SpawnObjError { pub kind: SpawnErrorKind, /// The task for which spawning was attempted - pub task: TaskObj, + pub task: FutureObj<()>, } /// The result of a failed spawn @@ -86,5 +86,5 @@ pub struct SpawnLocalObjError { pub kind: SpawnErrorKind, /// The task for which spawning was attempted - pub task: LocalTaskObj, + pub task: LocalFutureObj<()>, } diff --git a/src/libcore/task/task.rs b/src/libcore/task/future_obj.rs similarity index 50% rename from src/libcore/task/task.rs rename to src/libcore/task/future_obj.rs index c5a41873db427..3ed3bd51cf644 100644 --- a/src/libcore/task/task.rs +++ b/src/libcore/task/future_obj.rs @@ -14,63 +14,68 @@ use fmt; use future::Future; +use marker::PhantomData; use mem::PinMut; -use super::{Context, Poll}; +use task::{Context, Poll}; -/// A custom trait object for polling tasks, roughly akin to -/// `Box>`. -/// Contrary to `TaskObj`, `LocalTaskObj` does not have a `Send` bound. -pub struct LocalTaskObj { +/// A custom trait object for polling futures, roughly akin to +/// `Box>`. +/// Contrary to `FutureObj`, `LocalFutureObj` does not have a `Send` bound. +pub struct LocalFutureObj { ptr: *mut (), - poll_fn: unsafe fn(*mut (), &mut Context) -> Poll<()>, + poll_fn: unsafe fn(*mut (), &mut Context) -> Poll, drop_fn: unsafe fn(*mut ()), + _marker: PhantomData, } -impl LocalTaskObj { - /// Create a `LocalTaskObj` from a custom trait object representation. +impl LocalFutureObj { + /// Create a `LocalFutureObj` from a custom trait object representation. #[inline] - pub fn new(t: T) -> LocalTaskObj { - LocalTaskObj { - ptr: t.into_raw(), - poll_fn: T::poll, - drop_fn: T::drop, + pub fn new>(f: F) -> LocalFutureObj { + LocalFutureObj { + ptr: f.into_raw(), + poll_fn: F::poll, + drop_fn: F::drop, + _marker: PhantomData, } } - /// Converts the `LocalTaskObj` into a `TaskObj` - /// To make this operation safe one has to ensure that the `UnsafeTask` - /// instance from which this `LocalTaskObj` was created actually implements - /// `Send`. - pub unsafe fn as_task_obj(self) -> TaskObj { - TaskObj(self) + /// Converts the `LocalFutureObj` into a `FutureObj` + /// To make this operation safe one has to ensure that the `UnsafeFutureObj` + /// instance from which this `LocalFutureObj` was created actually + /// implements `Send`. + #[inline] + pub unsafe fn as_future_obj(self) -> FutureObj { + FutureObj(self) } } -impl fmt::Debug for LocalTaskObj { +impl fmt::Debug for LocalFutureObj { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("LocalTaskObj") + f.debug_struct("LocalFutureObj") .finish() } } -impl From for LocalTaskObj { - fn from(task: TaskObj) -> LocalTaskObj { - task.0 +impl From> for LocalFutureObj { + #[inline] + fn from(f: FutureObj) -> LocalFutureObj { + f.0 } } -impl Future for LocalTaskObj { - type Output = (); +impl Future for LocalFutureObj { + type Output = T; #[inline] - fn poll(self: PinMut, cx: &mut Context) -> Poll<()> { + fn poll(self: PinMut, cx: &mut Context) -> Poll { unsafe { (self.poll_fn)(self.ptr, cx) } } } -impl Drop for LocalTaskObj { +impl Drop for LocalFutureObj { fn drop(&mut self) { unsafe { (self.drop_fn)(self.ptr) @@ -78,38 +83,38 @@ impl Drop for LocalTaskObj { } } -/// A custom trait object for polling tasks, roughly akin to -/// `Box + Send>`. -pub struct TaskObj(LocalTaskObj); +/// A custom trait object for polling futures, roughly akin to +/// `Box> + Send`. +pub struct FutureObj(LocalFutureObj); -unsafe impl Send for TaskObj {} +unsafe impl Send for FutureObj {} -impl TaskObj { - /// Create a `TaskObj` from a custom trait object representation. +impl FutureObj { + /// Create a `FutureObj` from a custom trait object representation. #[inline] - pub fn new(t: T) -> TaskObj { - TaskObj(LocalTaskObj::new(t)) + pub fn new + Send>(f: F) -> FutureObj { + FutureObj(LocalFutureObj::new(f)) } } -impl fmt::Debug for TaskObj { +impl fmt::Debug for FutureObj { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("TaskObj") + f.debug_struct("FutureObj") .finish() } } -impl Future for TaskObj { - type Output = (); +impl Future for FutureObj { + type Output = T; #[inline] - fn poll(self: PinMut, cx: &mut Context) -> Poll<()> { + fn poll(self: PinMut, cx: &mut Context) -> Poll { let pinned_field = unsafe { PinMut::map_unchecked(self, |x| &mut x.0) }; pinned_field.poll(cx) } } -/// A custom implementation of a task trait object for `TaskObj`, providing +/// A custom implementation of a future trait object for `FutureObj`, providing /// a hand-rolled vtable. /// /// This custom representation is typically used only in `no_std` contexts, @@ -118,25 +123,25 @@ impl Future for TaskObj { /// The implementor must guarantee that it is safe to call `poll` repeatedly (in /// a non-concurrent fashion) with the result of `into_raw` until `drop` is /// called. -pub unsafe trait UnsafeTask: 'static { +pub unsafe trait UnsafeFutureObj: 'static { /// Convert a owned instance into a (conceptually owned) void pointer. fn into_raw(self) -> *mut (); - /// Poll the task represented by the given void pointer. + /// Poll the future represented by the given void pointer. /// /// # Safety /// /// The trait implementor must guarantee that it is safe to repeatedly call /// `poll` with the result of `into_raw` until `drop` is called; such calls /// are not, however, allowed to race with each other or with calls to `drop`. - unsafe fn poll(task: *mut (), cx: &mut Context) -> Poll<()>; + unsafe fn poll(future: *mut (), cx: &mut Context) -> Poll; - /// Drops the task represented by the given void pointer. + /// Drops the future represented by the given void pointer. /// /// # Safety /// /// The trait implementor must guarantee that it is safe to call this /// function once per `into_raw` invocation; that call cannot race with /// other calls to `drop` or `poll`. - unsafe fn drop(task: *mut ()); + unsafe fn drop(future: *mut ()); } diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs index d167a37410553..06cd7a9dd773e 100644 --- a/src/libcore/task/mod.rs +++ b/src/libcore/task/mod.rs @@ -25,8 +25,8 @@ pub use self::executor::{ mod poll; pub use self::poll::Poll; -mod task; -pub use self::task::{TaskObj, LocalTaskObj, UnsafeTask}; +mod future_obj; +pub use self::future_obj::{FutureObj, LocalFutureObj, UnsafeFutureObj}; mod wake; pub use self::wake::{Waker, LocalWaker, UnsafeWake}; diff --git a/src/test/run-pass/async-await.rs b/src/test/run-pass/async-await.rs index 8b649f6ef7bbd..3a67750e77e6b 100644 --- a/src/test/run-pass/async-await.rs +++ b/src/test/run-pass/async-await.rs @@ -21,7 +21,7 @@ use std::sync::{ }; use std::task::{ Context, Poll, Wake, - Executor, TaskObj, SpawnObjError, + Executor, FutureObj, SpawnObjError, local_waker_from_nonlocal, }; @@ -37,7 +37,7 @@ impl Wake for Counter { struct NoopExecutor; impl Executor for NoopExecutor { - fn spawn_obj(&mut self, _: TaskObj) -> Result<(), SpawnObjError> { + fn spawn_obj(&mut self, _: FutureObj) -> Result<(), SpawnObjError> { Ok(()) } } diff --git a/src/test/run-pass/futures-api.rs b/src/test/run-pass/futures-api.rs index 3b5a1725b66cb..a427b82af6a6b 100644 --- a/src/test/run-pass/futures-api.rs +++ b/src/test/run-pass/futures-api.rs @@ -22,7 +22,7 @@ use std::sync::{ use std::task::{ Context, Poll, Wake, Waker, LocalWaker, - Executor, TaskObj, SpawnObjError, + Executor, FutureObj, SpawnObjError, local_waker, local_waker_from_nonlocal, }; @@ -44,7 +44,7 @@ impl Wake for Counter { struct NoopExecutor; impl Executor for NoopExecutor { - fn spawn_obj(&mut self, _: TaskObj) -> Result<(), SpawnObjError> { + fn spawn_obj(&mut self, _: FutureObj<()>) -> Result<(), SpawnObjError> { Ok(()) } } From 9f70e7fe3c4126bf8390a78e4740ade3261ac4df Mon Sep 17 00:00:00 2001 From: Josef Reinhard Brandl Date: Sat, 30 Jun 2018 19:37:28 +0200 Subject: [PATCH 02/11] Use `From` impls for `FutureObj<()>` --- src/liballoc/boxed.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index c1778ef101ac6..918ad657be909 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -950,29 +950,29 @@ unsafe impl + 'static> UnsafeFutureObj for PinBox } #[unstable(feature = "futures_api", issue = "50547")] -impl + Send + 'static> Into> for PinBox { - fn into(self) -> FutureObj { - FutureObj::new(self) +impl + Send + 'static> From> for FutureObj<()> { + fn from(boxed: PinBox) -> Self { + FutureObj::new(boxed) } } #[unstable(feature = "futures_api", issue = "50547")] -impl + Send + 'static> Into> for Box { - fn into(self) -> FutureObj { - FutureObj::new(PinBox::from(self)) +impl + Send + 'static> From> for FutureObj<()> { + fn from(boxed: Box) -> Self { + FutureObj::new(PinBox::from(boxed)) } } #[unstable(feature = "futures_api", issue = "50547")] -impl + 'static> Into> for PinBox { - fn into(self) -> LocalFutureObj { - LocalFutureObj::new(self) +impl + 'static> From> for LocalFutureObj<()> { + fn from(boxed: PinBox) -> Self { + LocalFutureObj::new(boxed) } } #[unstable(feature = "futures_api", issue = "50547")] -impl + 'static> Into> for Box { - fn into(self) -> LocalFutureObj { - LocalFutureObj::new(PinBox::from(self)) +impl + 'static> From> for LocalFutureObj<()> { + fn from(boxed: Box) -> Self { + LocalFutureObj::new(PinBox::from(boxed)) } } From d8bf2223672973f9d86f6c173793bcfce7890cd8 Mon Sep 17 00:00:00 2001 From: Josef Reinhard Brandl Date: Sat, 30 Jun 2018 21:16:44 +0200 Subject: [PATCH 03/11] Add lifetime to `FutureObj` --- src/liballoc/boxed.rs | 17 +++++----- src/libcore/{ => future}/future.rs | 2 -- src/libcore/{task => future}/future_obj.rs | 38 ++++++++++++---------- src/libcore/future/mod.rs | 21 ++++++++++++ src/libcore/task/executor.rs | 8 ++--- src/libcore/task/mod.rs | 3 -- src/test/run-pass/async-await.rs | 5 +-- src/test/run-pass/futures-api.rs | 5 +-- 8 files changed, 60 insertions(+), 39 deletions(-) rename src/libcore/{ => future}/future.rs (99%) rename src/libcore/{task => future}/future_obj.rs (79%) create mode 100644 src/libcore/future/mod.rs diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 918ad657be909..5984a992afc63 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -66,7 +66,8 @@ use core::marker::{Unpin, Unsize}; use core::mem::{self, PinMut}; use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState}; use core::ptr::{self, NonNull, Unique}; -use core::task::{Context, Poll, UnsafeFutureObj, FutureObj, LocalFutureObj}; +use core::future::{FutureObj, LocalFutureObj, UnsafeFutureObj}; +use core::task::{Context, Poll}; use core::convert::From; use raw_vec::RawVec; @@ -915,7 +916,7 @@ impl, U: ?Sized> CoerceUnsized> for PinBox {} impl Unpin for PinBox {} #[unstable(feature = "futures_api", issue = "50547")] -impl<'a, F: ?Sized + Future + Unpin> Future for Box { +impl Future for Box { type Output = F::Output; fn poll(mut self: PinMut, cx: &mut Context) -> Poll { @@ -924,7 +925,7 @@ impl<'a, F: ?Sized + Future + Unpin> Future for Box { } #[unstable(feature = "futures_api", issue = "50547")] -impl<'a, F: ?Sized + Future> Future for PinBox { +impl Future for PinBox { type Output = F::Output; fn poll(mut self: PinMut, cx: &mut Context) -> Poll { @@ -933,7 +934,7 @@ impl<'a, F: ?Sized + Future> Future for PinBox { } #[unstable(feature = "futures_api", issue = "50547")] -unsafe impl + 'static> UnsafeFutureObj for PinBox { +unsafe impl<'a, T, F: Future + 'a> UnsafeFutureObj<'a, T> for PinBox { fn into_raw(self) -> *mut () { PinBox::into_raw(self) as *mut () } @@ -950,28 +951,28 @@ unsafe impl + 'static> UnsafeFutureObj for PinBox } #[unstable(feature = "futures_api", issue = "50547")] -impl + Send + 'static> From> for FutureObj<()> { +impl<'a, F: Future + Send + 'a> From> for FutureObj<'a, ()> { fn from(boxed: PinBox) -> Self { FutureObj::new(boxed) } } #[unstable(feature = "futures_api", issue = "50547")] -impl + Send + 'static> From> for FutureObj<()> { +impl<'a, F: Future + Send + 'a> From> for FutureObj<'a, ()> { fn from(boxed: Box) -> Self { FutureObj::new(PinBox::from(boxed)) } } #[unstable(feature = "futures_api", issue = "50547")] -impl + 'static> From> for LocalFutureObj<()> { +impl<'a, F: Future + 'a> From> for LocalFutureObj<'a, ()> { fn from(boxed: PinBox) -> Self { LocalFutureObj::new(boxed) } } #[unstable(feature = "futures_api", issue = "50547")] -impl + 'static> From> for LocalFutureObj<()> { +impl<'a, F: Future + 'a> From> for LocalFutureObj<'a, ()> { fn from(boxed: Box) -> Self { LocalFutureObj::new(PinBox::from(boxed)) } diff --git a/src/libcore/future.rs b/src/libcore/future/future.rs similarity index 99% rename from src/libcore/future.rs rename to src/libcore/future/future.rs index 153cd6c0724d6..10b4ca9b0b27a 100644 --- a/src/libcore/future.rs +++ b/src/libcore/future/future.rs @@ -12,8 +12,6 @@ reason = "futures in libcore are unstable", issue = "50547")] -//! Asynchronous values. - use mem::PinMut; use marker::Unpin; use task::{self, Poll}; diff --git a/src/libcore/task/future_obj.rs b/src/libcore/future/future_obj.rs similarity index 79% rename from src/libcore/task/future_obj.rs rename to src/libcore/future/future_obj.rs index 3ed3bd51cf644..c60b8b97d34ec 100644 --- a/src/libcore/task/future_obj.rs +++ b/src/libcore/future/future_obj.rs @@ -21,22 +21,24 @@ use task::{Context, Poll}; /// A custom trait object for polling futures, roughly akin to /// `Box>`. /// Contrary to `FutureObj`, `LocalFutureObj` does not have a `Send` bound. -pub struct LocalFutureObj { +pub struct LocalFutureObj<'a, T> { ptr: *mut (), poll_fn: unsafe fn(*mut (), &mut Context) -> Poll, drop_fn: unsafe fn(*mut ()), - _marker: PhantomData, + _marker1: PhantomData, + _marker2: PhantomData<&'a ()>, } -impl LocalFutureObj { +impl<'a, T> LocalFutureObj<'a, T> { /// Create a `LocalFutureObj` from a custom trait object representation. #[inline] - pub fn new>(f: F) -> LocalFutureObj { + pub fn new + 'a>(f: F) -> LocalFutureObj<'a, T> { LocalFutureObj { ptr: f.into_raw(), poll_fn: F::poll, drop_fn: F::drop, - _marker: PhantomData, + _marker1: PhantomData, + _marker2: PhantomData, } } @@ -45,26 +47,26 @@ impl LocalFutureObj { /// instance from which this `LocalFutureObj` was created actually /// implements `Send`. #[inline] - pub unsafe fn as_future_obj(self) -> FutureObj { + pub unsafe fn as_future_obj(self) -> FutureObj<'a, T> { FutureObj(self) } } -impl fmt::Debug for LocalFutureObj { +impl<'a, T> fmt::Debug for LocalFutureObj<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("LocalFutureObj") .finish() } } -impl From> for LocalFutureObj { +impl<'a, T> From> for LocalFutureObj<'a, T> { #[inline] - fn from(f: FutureObj) -> LocalFutureObj { + fn from(f: FutureObj<'a, T>) -> LocalFutureObj<'a, T> { f.0 } } -impl Future for LocalFutureObj { +impl<'a, T> Future for LocalFutureObj<'a, T> { type Output = T; #[inline] @@ -75,7 +77,7 @@ impl Future for LocalFutureObj { } } -impl Drop for LocalFutureObj { +impl<'a, T> Drop for LocalFutureObj<'a, T> { fn drop(&mut self) { unsafe { (self.drop_fn)(self.ptr) @@ -85,26 +87,26 @@ impl Drop for LocalFutureObj { /// A custom trait object for polling futures, roughly akin to /// `Box> + Send`. -pub struct FutureObj(LocalFutureObj); +pub struct FutureObj<'a, T>(LocalFutureObj<'a, T>); -unsafe impl Send for FutureObj {} +unsafe impl<'a, T> Send for FutureObj<'a, T> {} -impl FutureObj { +impl<'a, T> FutureObj<'a, T> { /// Create a `FutureObj` from a custom trait object representation. #[inline] - pub fn new + Send>(f: F) -> FutureObj { + pub fn new + Send>(f: F) -> FutureObj<'a, T> { FutureObj(LocalFutureObj::new(f)) } } -impl fmt::Debug for FutureObj { +impl<'a, T> fmt::Debug for FutureObj<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("FutureObj") .finish() } } -impl Future for FutureObj { +impl<'a, T> Future for FutureObj<'a, T> { type Output = T; #[inline] @@ -123,7 +125,7 @@ impl Future for FutureObj { /// The implementor must guarantee that it is safe to call `poll` repeatedly (in /// a non-concurrent fashion) with the result of `into_raw` until `drop` is /// called. -pub unsafe trait UnsafeFutureObj: 'static { +pub unsafe trait UnsafeFutureObj<'a, T>: 'a { /// Convert a owned instance into a (conceptually owned) void pointer. fn into_raw(self) -> *mut (); diff --git a/src/libcore/future/mod.rs b/src/libcore/future/mod.rs new file mode 100644 index 0000000000000..f9361a0f4e7a3 --- /dev/null +++ b/src/libcore/future/mod.rs @@ -0,0 +1,21 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![unstable(feature = "futures_api", + reason = "futures in libcore are unstable", + issue = "50547")] + +//! Asynchronous values. + +mod future; +pub use self::future::Future; + +mod future_obj; +pub use self::future_obj::{FutureObj, LocalFutureObj, UnsafeFutureObj}; diff --git a/src/libcore/task/executor.rs b/src/libcore/task/executor.rs index 55ea5e724c1cc..f1db5093e9880 100644 --- a/src/libcore/task/executor.rs +++ b/src/libcore/task/executor.rs @@ -13,7 +13,7 @@ issue = "50547")] use fmt; -use super::{FutureObj, LocalFutureObj}; +use future::{FutureObj, LocalFutureObj}; /// A task executor. /// @@ -29,7 +29,7 @@ pub trait Executor { /// /// The executor may be unable to spawn tasks, either because it has /// been shut down or is resource-constrained. - fn spawn_obj(&mut self, task: FutureObj<()>) -> Result<(), SpawnObjError>; + fn spawn_obj(&mut self, task: FutureObj<'static, ()>) -> Result<(), SpawnObjError>; /// Determine whether the executor is able to spawn new tasks. /// @@ -76,7 +76,7 @@ pub struct SpawnObjError { pub kind: SpawnErrorKind, /// The task for which spawning was attempted - pub task: FutureObj<()>, + pub task: FutureObj<'static, ()>, } /// The result of a failed spawn @@ -86,5 +86,5 @@ pub struct SpawnLocalObjError { pub kind: SpawnErrorKind, /// The task for which spawning was attempted - pub task: LocalFutureObj<()>, + pub task: LocalFutureObj<'static, ()>, } diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs index 06cd7a9dd773e..c4f075361640f 100644 --- a/src/libcore/task/mod.rs +++ b/src/libcore/task/mod.rs @@ -25,8 +25,5 @@ pub use self::executor::{ mod poll; pub use self::poll::Poll; -mod future_obj; -pub use self::future_obj::{FutureObj, LocalFutureObj, UnsafeFutureObj}; - mod wake; pub use self::wake::{Waker, LocalWaker, UnsafeWake}; diff --git a/src/test/run-pass/async-await.rs b/src/test/run-pass/async-await.rs index 3a67750e77e6b..0ac37485d3dc8 100644 --- a/src/test/run-pass/async-await.rs +++ b/src/test/run-pass/async-await.rs @@ -19,9 +19,10 @@ use std::sync::{ Arc, atomic::{self, AtomicUsize}, }; +use std::future::FutureObj; use std::task::{ Context, Poll, Wake, - Executor, FutureObj, SpawnObjError, + Executor, SpawnObjError, local_waker_from_nonlocal, }; @@ -37,7 +38,7 @@ impl Wake for Counter { struct NoopExecutor; impl Executor for NoopExecutor { - fn spawn_obj(&mut self, _: FutureObj) -> Result<(), SpawnObjError> { + fn spawn_obj(&mut self, _: FutureObj<'static, ()>) -> Result<(), SpawnObjError> { Ok(()) } } diff --git a/src/test/run-pass/futures-api.rs b/src/test/run-pass/futures-api.rs index a427b82af6a6b..6cb975a9560b9 100644 --- a/src/test/run-pass/futures-api.rs +++ b/src/test/run-pass/futures-api.rs @@ -19,10 +19,11 @@ use std::sync::{ Arc, atomic::{self, AtomicUsize}, }; +use std::future::FutureObj; use std::task::{ Context, Poll, Wake, Waker, LocalWaker, - Executor, FutureObj, SpawnObjError, + Executor, SpawnObjError, local_waker, local_waker_from_nonlocal, }; @@ -44,7 +45,7 @@ impl Wake for Counter { struct NoopExecutor; impl Executor for NoopExecutor { - fn spawn_obj(&mut self, _: FutureObj<()>) -> Result<(), SpawnObjError> { + fn spawn_obj(&mut self, _: FutureObj<'static, ()>) -> Result<(), SpawnObjError> { Ok(()) } } From 042928f0f591a63e0a2ed31c932015f4248d4fa7 Mon Sep 17 00:00:00 2001 From: Josef Reinhard Brandl Date: Sun, 1 Jul 2018 09:28:16 +0200 Subject: [PATCH 04/11] `UnsafeFutureObj` impl for `PinMut` --- src/liballoc/boxed.rs | 13 ++++++------- src/libcore/future/future_obj.rs | 6 +++--- src/libcore/mem.rs | 17 +++++++++++++++++ 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 5984a992afc63..7f6d27088b77c 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -58,17 +58,16 @@ use core::any::Any; use core::borrow; use core::cmp::Ordering; +use core::convert::From; use core::fmt; -use core::future::Future; +use core::future::{Future, FutureObj, LocalFutureObj, UnsafeFutureObj}; use core::hash::{Hash, Hasher}; use core::iter::FusedIterator; use core::marker::{Unpin, Unsize}; use core::mem::{self, PinMut}; use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState}; use core::ptr::{self, NonNull, Unique}; -use core::future::{FutureObj, LocalFutureObj, UnsafeFutureObj}; use core::task::{Context, Poll}; -use core::convert::From; use raw_vec::RawVec; use str::from_boxed_utf8_unchecked; @@ -939,14 +938,14 @@ unsafe impl<'a, T, F: Future + 'a> UnsafeFutureObj<'a, T> for PinBox PinBox::into_raw(self) as *mut () } - unsafe fn poll(task: *mut (), cx: &mut Context) -> Poll { - let ptr = task as *mut F; + unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll { + let ptr = ptr as *mut F; let pin: PinMut = PinMut::new_unchecked(&mut *ptr); pin.poll(cx) } - unsafe fn drop(task: *mut ()) { - drop(PinBox::from_raw(task as *mut F)) + unsafe fn drop(ptr: *mut ()) { + drop(PinBox::from_raw(ptr as *mut F)) } } diff --git a/src/libcore/future/future_obj.rs b/src/libcore/future/future_obj.rs index c60b8b97d34ec..67bd3de98c1ae 100644 --- a/src/libcore/future/future_obj.rs +++ b/src/libcore/future/future_obj.rs @@ -126,7 +126,7 @@ impl<'a, T> Future for FutureObj<'a, T> { /// a non-concurrent fashion) with the result of `into_raw` until `drop` is /// called. pub unsafe trait UnsafeFutureObj<'a, T>: 'a { - /// Convert a owned instance into a (conceptually owned) void pointer. + /// Convert an owned instance into a (conceptually owned) void pointer. fn into_raw(self) -> *mut (); /// Poll the future represented by the given void pointer. @@ -136,7 +136,7 @@ pub unsafe trait UnsafeFutureObj<'a, T>: 'a { /// The trait implementor must guarantee that it is safe to repeatedly call /// `poll` with the result of `into_raw` until `drop` is called; such calls /// are not, however, allowed to race with each other or with calls to `drop`. - unsafe fn poll(future: *mut (), cx: &mut Context) -> Poll; + unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll; /// Drops the future represented by the given void pointer. /// @@ -145,5 +145,5 @@ pub unsafe trait UnsafeFutureObj<'a, T>: 'a { /// The trait implementor must guarantee that it is safe to call this /// function once per `into_raw` invocation; that call cannot race with /// other calls to `drop` or `poll`. - unsafe fn drop(future: *mut ()); + unsafe fn drop(ptr: *mut ()); } diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 08bd9289ab487..5bc55300a9738 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -18,10 +18,12 @@ use clone; use cmp; use fmt; +use future::{Future, UnsafeFutureObj}; use hash; use intrinsics; use marker::{Copy, PhantomData, Sized, Unpin, Unsize}; use ptr; +use task::{Context, Poll}; use ops::{Deref, DerefMut, CoerceUnsized}; #[stable(feature = "rust1", since = "1.0.0")] @@ -1227,3 +1229,18 @@ impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for PinM #[unstable(feature = "pin", issue = "49150")] impl<'a, T: ?Sized> Unpin for PinMut<'a, T> {} + +#[unstable(feature = "futures_api", issue = "50547")] +unsafe impl<'a, T, F: Future + 'a> UnsafeFutureObj<'a, T> for PinMut<'a, F> { + fn into_raw(self) -> *mut () { + unsafe { PinMut::get_mut_unchecked(self) as *mut F as *mut () } + } + + unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll { + PinMut::new_unchecked(&mut *(ptr as *mut F)).poll(cx) + } + + unsafe fn drop(ptr: *mut ()) { + drop(PinMut::new_unchecked(&mut *(ptr as *mut F))); + } +} From dd3b0337ff22260ef9dfc1bfcf58bd18386d4cbe Mon Sep 17 00:00:00 2001 From: Josef Reinhard Brandl Date: Sun, 1 Jul 2018 14:58:40 +0200 Subject: [PATCH 05/11] Improve doc comments for `FutureObj` --- src/libcore/future/future_obj.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libcore/future/future_obj.rs b/src/libcore/future/future_obj.rs index 67bd3de98c1ae..b42fd2b5bd7a4 100644 --- a/src/libcore/future/future_obj.rs +++ b/src/libcore/future/future_obj.rs @@ -19,7 +19,7 @@ use mem::PinMut; use task::{Context, Poll}; /// A custom trait object for polling futures, roughly akin to -/// `Box>`. +/// `Box + 'a>`. /// Contrary to `FutureObj`, `LocalFutureObj` does not have a `Send` bound. pub struct LocalFutureObj<'a, T> { ptr: *mut (), @@ -86,7 +86,7 @@ impl<'a, T> Drop for LocalFutureObj<'a, T> { } /// A custom trait object for polling futures, roughly akin to -/// `Box> + Send`. +/// `Box + Send + 'a>`. pub struct FutureObj<'a, T>(LocalFutureObj<'a, T>); unsafe impl<'a, T> Send for FutureObj<'a, T> {} @@ -135,7 +135,8 @@ pub unsafe trait UnsafeFutureObj<'a, T>: 'a { /// /// The trait implementor must guarantee that it is safe to repeatedly call /// `poll` with the result of `into_raw` until `drop` is called; such calls - /// are not, however, allowed to race with each other or with calls to `drop`. + /// are not, however, allowed to race with each other or with calls to + /// `drop`. unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll; /// Drops the future represented by the given void pointer. From 4e617291c2c7b918ec9a183dd2ce72ac92edf940 Mon Sep 17 00:00:00 2001 From: Josef Reinhard Brandl Date: Sun, 1 Jul 2018 15:27:53 +0200 Subject: [PATCH 06/11] Make `drop` method for `PinMut`'s `UnsafeFutureObj` impl empty --- src/libcore/mem.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 5bc55300a9738..b83c2e21a1a44 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -1240,7 +1240,5 @@ unsafe impl<'a, T, F: Future + 'a> UnsafeFutureObj<'a, T> for PinMut PinMut::new_unchecked(&mut *(ptr as *mut F)).poll(cx) } - unsafe fn drop(ptr: *mut ()) { - drop(PinMut::new_unchecked(&mut *(ptr as *mut F))); - } + unsafe fn drop(_ptr: *mut ()) {} } From 9eee0d2288c067be081f2ca35f5b2d3cfc95fcf2 Mon Sep 17 00:00:00 2001 From: Josef Reinhard Brandl Date: Mon, 2 Jul 2018 18:16:36 +0200 Subject: [PATCH 07/11] Fix naming convention issue --- src/libcore/future/future_obj.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/future/future_obj.rs b/src/libcore/future/future_obj.rs index b42fd2b5bd7a4..86fe9825dedd8 100644 --- a/src/libcore/future/future_obj.rs +++ b/src/libcore/future/future_obj.rs @@ -47,7 +47,7 @@ impl<'a, T> LocalFutureObj<'a, T> { /// instance from which this `LocalFutureObj` was created actually /// implements `Send`. #[inline] - pub unsafe fn as_future_obj(self) -> FutureObj<'a, T> { + pub unsafe fn into_future_obj(self) -> FutureObj<'a, T> { FutureObj(self) } } From cb2c7570db807eab35b3decd813f5cbec844ddb3 Mon Sep 17 00:00:00 2001 From: Josef Reinhard Brandl Date: Mon, 2 Jul 2018 18:55:42 +0200 Subject: [PATCH 08/11] Add explanation for custom trait object --- src/libcore/future/future_obj.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/libcore/future/future_obj.rs b/src/libcore/future/future_obj.rs index 86fe9825dedd8..173e381ca50de 100644 --- a/src/libcore/future/future_obj.rs +++ b/src/libcore/future/future_obj.rs @@ -20,7 +20,15 @@ use task::{Context, Poll}; /// A custom trait object for polling futures, roughly akin to /// `Box + 'a>`. -/// Contrary to `FutureObj`, `LocalFutureObj` does not have a `Send` bound. +/// +/// This custom trait object was introduced for two reasons: +/// - Currently it is not possible to take `dyn Trait` by value and +/// `Box` is not available in no_std contexts. +/// - The `Future` trait is currently not object safe: The `Future::poll` +/// method makes uses the arbitrary self types feature and traits in which +/// this feature is used are currently not object safe due to current compiler +/// limitations. (See tracking issue for arbitray self types for more +/// information #44874) pub struct LocalFutureObj<'a, T> { ptr: *mut (), poll_fn: unsafe fn(*mut (), &mut Context) -> Poll, @@ -87,6 +95,15 @@ impl<'a, T> Drop for LocalFutureObj<'a, T> { /// A custom trait object for polling futures, roughly akin to /// `Box + Send + 'a>`. +/// +/// This custom trait object was introduced for two reasons: +/// - Currently it is not possible to take `dyn Trait` by value and +/// `Box` is not available in no_std contexts. +/// - The `Future` trait is currently not object safe: The `Future::poll` +/// method makes uses the arbitrary self types feature and traits in which +/// this feature is used are currently not object safe due to current compiler +/// limitations. (See tracking issue for arbitray self types for more +/// information #44874) pub struct FutureObj<'a, T>(LocalFutureObj<'a, T>); unsafe impl<'a, T> Send for FutureObj<'a, T> {} From 5fde8b92372f02deaf5c7fb638447a60112f9015 Mon Sep 17 00:00:00 2001 From: Josef Reinhard Brandl Date: Mon, 2 Jul 2018 18:57:58 +0200 Subject: [PATCH 09/11] Remove unnecessary `PhantomData` field --- src/libcore/future/future_obj.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libcore/future/future_obj.rs b/src/libcore/future/future_obj.rs index 173e381ca50de..99f2127253883 100644 --- a/src/libcore/future/future_obj.rs +++ b/src/libcore/future/future_obj.rs @@ -33,8 +33,7 @@ pub struct LocalFutureObj<'a, T> { ptr: *mut (), poll_fn: unsafe fn(*mut (), &mut Context) -> Poll, drop_fn: unsafe fn(*mut ()), - _marker1: PhantomData, - _marker2: PhantomData<&'a ()>, + _marker: PhantomData<&'a ()>, } impl<'a, T> LocalFutureObj<'a, T> { @@ -45,8 +44,7 @@ impl<'a, T> LocalFutureObj<'a, T> { ptr: f.into_raw(), poll_fn: F::poll, drop_fn: F::drop, - _marker1: PhantomData, - _marker2: PhantomData, + _marker: PhantomData, } } From ae408947de1311f9673d0ae34028933cd191ac90 Mon Sep 17 00:00:00 2001 From: Josef Reinhard Brandl Date: Mon, 2 Jul 2018 19:07:59 +0200 Subject: [PATCH 10/11] Implement `UnsafeFutureObj` for `&mut Future` --- src/liballoc/boxed.rs | 4 +++- src/libcore/future/future_obj.rs | 16 +++++++++++++++- src/libcore/mem.rs | 4 +++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 7f6d27088b77c..fabeaa1c144bf 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -933,7 +933,9 @@ impl Future for PinBox { } #[unstable(feature = "futures_api", issue = "50547")] -unsafe impl<'a, T, F: Future + 'a> UnsafeFutureObj<'a, T> for PinBox { +unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for PinBox + where F: Future + 'a +{ fn into_raw(self) -> *mut () { PinBox::into_raw(self) as *mut () } diff --git a/src/libcore/future/future_obj.rs b/src/libcore/future/future_obj.rs index 99f2127253883..98c504a3f7bef 100644 --- a/src/libcore/future/future_obj.rs +++ b/src/libcore/future/future_obj.rs @@ -14,7 +14,7 @@ use fmt; use future::Future; -use marker::PhantomData; +use marker::{PhantomData, Unpin}; use mem::PinMut; use task::{Context, Poll}; @@ -163,3 +163,17 @@ pub unsafe trait UnsafeFutureObj<'a, T>: 'a { /// other calls to `drop` or `poll`. unsafe fn drop(ptr: *mut ()); } + +unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for &'a mut F + where F: Future + Unpin + 'a +{ + fn into_raw(self) -> *mut () { + self as *mut F as *mut () + } + + unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll { + PinMut::new_unchecked(&mut *(ptr as *mut F)).poll(cx) + } + + unsafe fn drop(_ptr: *mut ()) {} +} diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index b83c2e21a1a44..84173654655eb 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -1231,7 +1231,9 @@ impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for PinM impl<'a, T: ?Sized> Unpin for PinMut<'a, T> {} #[unstable(feature = "futures_api", issue = "50547")] -unsafe impl<'a, T, F: Future + 'a> UnsafeFutureObj<'a, T> for PinMut<'a, F> { +unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for PinMut<'a, F> + where F: Future + 'a +{ fn into_raw(self) -> *mut () { unsafe { PinMut::get_mut_unchecked(self) as *mut F as *mut () } } From e666c2bd0742cbf88ff9fa26cfc194099a139589 Mon Sep 17 00:00:00 2001 From: Josef Reinhard Brandl Date: Mon, 2 Jul 2018 19:21:32 +0200 Subject: [PATCH 11/11] Implemented `UnsafeFutureObj` on `Box` --- src/liballoc/boxed.rs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index fabeaa1c144bf..fb16bdf0ab43a 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -932,6 +932,25 @@ impl Future for PinBox { } } +#[unstable(feature = "futures_api", issue = "50547")] +unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Box + where F: Future + 'a +{ + fn into_raw(self) -> *mut () { + Box::into_raw(self) as *mut () + } + + unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll { + let ptr = ptr as *mut F; + let pin: PinMut = PinMut::new_unchecked(&mut *ptr); + pin.poll(cx) + } + + unsafe fn drop(ptr: *mut ()) { + drop(Box::from_raw(ptr as *mut F)) + } +} + #[unstable(feature = "futures_api", issue = "50547")] unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for PinBox where F: Future + 'a @@ -961,7 +980,7 @@ impl<'a, F: Future + Send + 'a> From> for FutureObj<'a, ( #[unstable(feature = "futures_api", issue = "50547")] impl<'a, F: Future + Send + 'a> From> for FutureObj<'a, ()> { fn from(boxed: Box) -> Self { - FutureObj::new(PinBox::from(boxed)) + FutureObj::new(boxed) } } @@ -975,6 +994,6 @@ impl<'a, F: Future + 'a> From> for LocalFutureObj<'a, ()> #[unstable(feature = "futures_api", issue = "50547")] impl<'a, F: Future + 'a> From> for LocalFutureObj<'a, ()> { fn from(boxed: Box) -> Self { - LocalFutureObj::new(PinBox::from(boxed)) + LocalFutureObj::new(boxed) } }