diff options
| author | Taylor Cramer <cramertj@google.com> | 2018-06-06 15:50:59 -0700 |
|---|---|---|
| committer | Taylor Cramer <cramertj@google.com> | 2018-06-21 22:36:36 -0700 |
| commit | cf844b547dbec1f23982fca8e07ec65800ed5d6d (patch) | |
| tree | a5420599dea5829f105d2a12bb14a3102141a749 /src/libstd | |
| parent | 589446e19cbf7a2c7eddf80b490992d31134015c (diff) | |
| download | rust-cf844b547dbec1f23982fca8e07ec65800ed5d6d.tar.gz rust-cf844b547dbec1f23982fca8e07ec65800ed5d6d.zip | |
async await desugaring and tests
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/lib.rs | 4 | ||||
| -rw-r--r-- | src/libstd/macros.rs | 20 | ||||
| -rw-r--r-- | src/libstd/raw.rs | 110 |
3 files changed, 132 insertions, 2 deletions
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index a6061e96ae5..c74cd3feca3 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -263,6 +263,7 @@ #![feature(fn_traits)] #![feature(fnbox)] #![feature(futures_api)] +#![feature(generator_trait)] #![feature(hashmap_internals)] #![feature(int_error_internals)] #![feature(integer_atomics)] @@ -410,8 +411,6 @@ pub use core::ops; #[stable(feature = "rust1", since = "1.0.0")] pub use core::ptr; #[stable(feature = "rust1", since = "1.0.0")] -pub use core::raw; -#[stable(feature = "rust1", since = "1.0.0")] pub use core::result; #[stable(feature = "rust1", since = "1.0.0")] pub use core::option; @@ -496,6 +495,7 @@ pub mod os; pub mod panic; pub mod path; pub mod process; +pub mod raw; pub mod sync; pub mod time; diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 8da70f5717e..812b0b9fdda 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -213,6 +213,26 @@ macro_rules! eprintln { ($fmt:expr, $($arg:tt)*) => (eprint!(concat!($fmt, "\n"), $($arg)*)); } +#[macro_export] +#[unstable(feature = "await_macro", issue = "50547")] +#[allow_internal_unstable] +macro_rules! await { + ($e:expr) => { { + let mut pinned = $e; + let mut pinned = unsafe { ::core::mem::PinMut::new_unchecked(&mut pinned) }; + loop { + match ::std::raw::with_get_cx(|cx| + ::core::future::Future::poll(pinned.reborrow(), cx)) + { + // FIXME(cramertj) prior to stabilizing await, we have to ensure that this + // can't be used to create a generator on stable via `|| await!()`. + ::core::task::Poll::Pending => yield, + ::core::task::Poll::Ready(x) => break x, + } + } + } } +} + /// A macro to select an event from a number of receivers. /// /// This macro is used to wait for the first event to occur on a number of diff --git a/src/libstd/raw.rs b/src/libstd/raw.rs new file mode 100644 index 00000000000..62fd42c4de7 --- /dev/null +++ b/src/libstd/raw.rs @@ -0,0 +1,110 @@ +// Copyright 2013 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(missing_docs)] +#![unstable(feature = "raw", issue = "27751")] + +//! Contains struct definitions for the layout of compiler built-in types. +//! +//! They can be used as targets of transmutes in unsafe code for manipulating +//! the raw representations directly. +//! +//! Their definition should always match the ABI defined in `rustc::back::abi`. + +use core::cell::Cell; +use core::future::Future; +use core::marker::Unpin; +use core::mem::PinMut; +use core::option::Option; +use core::ptr::NonNull; +use core::task::{self, Poll}; +use core::ops::{Drop, Generator, GeneratorState}; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::raw::*; + +/// Wrap a future in a generator. +/// +/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give +/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`). +#[unstable(feature = "gen_future", issue = "50547")] +pub fn future_from_generator<T: Generator<Yield = ()>>(x: T) -> impl Future<Output = T::Return> { + GenFuture(x) +} + +/// A wrapper around generators used to implement `Future` for `async`/`await` code. +#[unstable(feature = "gen_future", issue = "50547")] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] +struct GenFuture<T: Generator<Yield = ()>>(T); + +// We rely on the fact that async/await futures are immovable in order to create +// self-referential borrows in the underlying generator. +impl<T: Generator<Yield = ()>> !Unpin for GenFuture<T> {} + +#[unstable(feature = "gen_future", issue = "50547")] +impl<T: Generator<Yield = ()>> Future for GenFuture<T> { + type Output = T::Return; + fn poll(self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> { + with_set_cx(cx, || match unsafe { PinMut::get_mut(self).0.resume() } { + GeneratorState::Yielded(()) => Poll::Pending, + GeneratorState::Complete(x) => Poll::Ready(x), + }) + } +} + +thread_local! { + static TLS_CX: Cell<Option<NonNull<task::Context<'static>>>> = Cell::new(None); +} + +struct SetOnDrop(Option<NonNull<task::Context<'static>>>); + +impl Drop for SetOnDrop { + fn drop(&mut self) { + TLS_CX.with(|tls_cx| { + tls_cx.set(self.0.take()); + }); + } +} + +#[unstable(feature = "gen_future", issue = "50547")] +pub fn with_set_cx<F, R>(cx: &mut task::Context, f: F) -> R +where + F: FnOnce() -> R +{ + let old_cx = TLS_CX.with(|tls_cx| { + let old_cx = tls_cx.get(); + tls_cx.set(NonNull::new( + cx as *mut task::Context as *mut () as *mut task::Context<'static>)); + old_cx + }); + let _reset_cx = SetOnDrop(old_cx); + let res = f(); + res +} + +#[unstable(feature = "gen_future", issue = "50547")] +pub fn with_get_cx<F, R>(f: F) -> R +where + F: FnOnce(&mut task::Context) -> R +{ + let cx_ptr = TLS_CX.with(|tls_cx| { + let cx_ptr = tls_cx.get(); + // Clear the entry so that nested `with_get_cx` calls + // will fail or set their own value. + tls_cx.set(None); + cx_ptr + }); + let _reset_cx = SetOnDrop(cx_ptr); + + let mut cx_ptr = cx_ptr.expect( + "TLS task::Context not set. This is a rustc bug. \ + Please file an issue on https://github.com/rust-lang/rust."); + unsafe { f(cx_ptr.as_mut()) } +} |
