From cf844b547dbec1f23982fca8e07ec65800ed5d6d Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Wed, 6 Jun 2018 15:50:59 -0700 Subject: async await desugaring and tests --- src/libstd/lib.rs | 4 +- src/libstd/macros.rs | 20 ++++++++++ src/libstd/raw.rs | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 src/libstd/raw.rs (limited to 'src/libstd') 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 or the MIT license +// , 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>(x: T) -> impl Future { + 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); + +// We rely on the fact that async/await futures are immovable in order to create +// self-referential borrows in the underlying generator. +impl> !Unpin for GenFuture {} + +#[unstable(feature = "gen_future", issue = "50547")] +impl> Future for GenFuture { + type Output = T::Return; + fn poll(self: PinMut, cx: &mut task::Context) -> Poll { + 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>>> = Cell::new(None); +} + +struct SetOnDrop(Option>>); + +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(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: 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()) } +} -- cgit 1.4.1-3-g733a5 From f744ac553872afaf8c44f842dc0f247a623841b0 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Tue, 19 Jun 2018 10:36:16 -0700 Subject: Allow unsafe code inside of await macro --- src/libstd/macros.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/libstd') diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 812b0b9fdda..1f2a6e2bfea 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -216,6 +216,7 @@ macro_rules! eprintln { #[macro_export] #[unstable(feature = "await_macro", issue = "50547")] #[allow_internal_unstable] +#[allow_internal_unsafe] macro_rules! await { ($e:expr) => { { let mut pinned = $e; -- cgit 1.4.1-3-g733a5 From ee51a3c10aa26b6e6c4e86622181d4a3d396fb34 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Fri, 22 Jun 2018 11:36:01 -0700 Subject: Review nits and updates Move future_from_generator out of raw Update await to use $crate Renumber errors --- src/librustc/diagnostics.rs | 6 +- src/librustc/hir/lowering.rs | 15 +-- src/libstd/future.rs | 106 +++++++++++++++++++++ src/libstd/lib.rs | 35 +++---- src/libstd/macros.rs | 10 +- src/libstd/raw.rs | 110 ---------------------- src/test/ui/async-fn-multiple-lifetimes.stderr | 6 +- src/test/ui/no-args-non-move-async-closure.stderr | 4 +- 8 files changed, 145 insertions(+), 147 deletions(-) create mode 100644 src/libstd/future.rs delete mode 100644 src/libstd/raw.rs (limited to 'src/libstd') diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 6e6b15bdff7..09153c144ae 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -2134,7 +2134,7 @@ register_diagnostics! { E0906, // closures cannot be static - E0703, // multiple different lifetimes used in arguments of `async fn` - E0704, // multiple elided lifetimes used in arguments of `async fn` - E0705, // `async` non-`move` closures with arguments are not currently supported + E0725, // multiple different lifetimes used in arguments of `async fn` + E0726, // multiple elided lifetimes used in arguments of `async fn` + E0727, // `async` non-`move` closures with arguments are not currently supported } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index ad8da5a4350..aeef93a1740 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -877,7 +877,7 @@ impl<'a> LoweringContext<'a> { let unstable_span = self.allow_internal_unstable(CompilerDesugaringKind::Async, span); let gen_future = self.expr_std_path( - unstable_span, &["raw", "future_from_generator"], None, ThinVec::new()); + unstable_span, &["future", "future_from_generator"], None, ThinVec::new()); hir::ExprCall(P(gen_future), hir_vec![generator]) } @@ -2049,7 +2049,7 @@ impl<'a> LoweringContext<'a> { struct_span_err!( self.context.sess, current_lt_span.between(lifetime.span), - E0703, + E0725, "multiple different lifetimes used in arguments of `async fn`", ) .span_label(current_lt_span, "first lifetime here") @@ -2061,7 +2061,7 @@ impl<'a> LoweringContext<'a> { struct_span_err!( self.context.sess, current_lt_span.between(lifetime.span), - E0704, + E0726, "multiple elided lifetimes used in arguments of `async fn`", ) .span_label(current_lt_span, "first lifetime here") @@ -2582,9 +2582,10 @@ impl<'a> LoweringContext<'a> { let fn_def_id = self.resolver.definitions().local_def_id(id); self.with_new_scopes(|this| { - // Note: we can use non-async decl here because lower_body - // only cares about the input argument patterns, - // not the return types. + // Note: we don't need to change the return type from `T` to + // `impl Future` here because lower_body + // only cares about the input argument patterns in the function + // declaration (decl), not the return types. let body_id = this.lower_body(Some(decl), |this| { if let IsAsync::Async(async_node_id) = header.asyncness { let async_expr = this.make_async_expr( @@ -3560,7 +3561,7 @@ impl<'a> LoweringContext<'a> { struct_span_err!( this.sess, fn_decl_span, - E0705, + E0727, "`async` non-`move` closures with arguments \ are not currently supported", ) diff --git a/src/libstd/future.rs b/src/libstd/future.rs new file mode 100644 index 00000000000..abacb862656 --- /dev/null +++ b/src/libstd/future.rs @@ -0,0 +1,106 @@ +// 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. + +//! Asynchronous values. + +use core::cell::Cell; +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}; + +#[doc(inline)] +pub use core::future::*; + +/// 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>(x: T) -> impl Future { + 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); + +// We rely on the fact that async/await futures are immovable in order to create +// self-referential borrows in the underlying generator. +impl> !Unpin for GenFuture {} + +#[unstable(feature = "gen_future", issue = "50547")] +impl> Future for GenFuture { + type Output = T::Return; + fn poll(self: PinMut, cx: &mut task::Context) -> Poll { + set_task_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>>> = Cell::new(None); +} + +struct SetOnDrop(Option>>); + +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")] +/// Sets the thread-local task context used by async/await futures. +pub fn set_task_cx(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")] +/// Retrieves the thread-local task context used by async/await futures. +/// +/// Panics if no task has been set or if the task context has already been +/// retrived by a surrounding call to get_task_cx. +pub fn get_task_cx(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()) } +} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index c74cd3feca3..caad924ea5b 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -411,6 +411,8 @@ 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; @@ -461,22 +463,6 @@ pub use core::u128; #[stable(feature = "core_hint", since = "1.27.0")] pub use core::hint; -#[unstable(feature = "futures_api", - reason = "futures in libcore are unstable", - issue = "50547")] -pub mod task { - //! Types and Traits for working with asynchronous tasks. - #[doc(inline)] - pub use core::task::*; - #[doc(inline)] - pub use alloc_crate::task::*; -} - -#[unstable(feature = "futures_api", - reason = "futures in libcore are unstable", - issue = "50547")] -pub use core::future; - pub mod f32; pub mod f64; @@ -495,10 +481,25 @@ pub mod os; pub mod panic; pub mod path; pub mod process; -pub mod raw; pub mod sync; pub mod time; +#[unstable(feature = "futures_api", + reason = "futures in libcore are unstable", + issue = "50547")] +pub mod task { + //! Types and Traits for working with asynchronous tasks. + #[doc(inline)] + pub use core::task::*; + #[doc(inline)] + pub use alloc_crate::task::*; +} + +#[unstable(feature = "futures_api", + reason = "futures in libcore are unstable", + issue = "50547")] +pub mod future; + // Platform-abstraction modules #[macro_use] mod sys_common; diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 1f2a6e2bfea..1e9da42d40d 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -220,15 +220,15 @@ macro_rules! eprintln { macro_rules! await { ($e:expr) => { { let mut pinned = $e; - let mut pinned = unsafe { ::core::mem::PinMut::new_unchecked(&mut pinned) }; + let mut pinned = unsafe { $crate::mem::PinMut::new_unchecked(&mut pinned) }; loop { - match ::std::raw::with_get_cx(|cx| - ::core::future::Future::poll(pinned.reborrow(), cx)) + match $crate::future::get_task_cx(|cx| + $crate::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, + $crate::task::Poll::Pending => yield, + $crate::task::Poll::Ready(x) => break x, } } } } diff --git a/src/libstd/raw.rs b/src/libstd/raw.rs deleted file mode 100644 index 62fd42c4de7..00000000000 --- a/src/libstd/raw.rs +++ /dev/null @@ -1,110 +0,0 @@ -// 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 or the MIT license -// , 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>(x: T) -> impl Future { - 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); - -// We rely on the fact that async/await futures are immovable in order to create -// self-referential borrows in the underlying generator. -impl> !Unpin for GenFuture {} - -#[unstable(feature = "gen_future", issue = "50547")] -impl> Future for GenFuture { - type Output = T::Return; - fn poll(self: PinMut, cx: &mut task::Context) -> Poll { - 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>>> = Cell::new(None); -} - -struct SetOnDrop(Option>>); - -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(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: 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()) } -} diff --git a/src/test/ui/async-fn-multiple-lifetimes.stderr b/src/test/ui/async-fn-multiple-lifetimes.stderr index 085b9499a41..d76bfc5d0e1 100644 --- a/src/test/ui/async-fn-multiple-lifetimes.stderr +++ b/src/test/ui/async-fn-multiple-lifetimes.stderr @@ -1,4 +1,4 @@ -error[E0703]: multiple different lifetimes used in arguments of `async fn` +error[E0725]: multiple different lifetimes used in arguments of `async fn` --> $DIR/async-fn-multiple-lifetimes.rs:17:49 | LL | async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8) {} @@ -8,7 +8,7 @@ LL | async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8) {} | = help: `async fn` can only accept borrowed values with identical lifetimes -error[E0704]: multiple elided lifetimes used in arguments of `async fn` +error[E0726]: multiple elided lifetimes used in arguments of `async fn` --> $DIR/async-fn-multiple-lifetimes.rs:26:39 | LL | async fn multiple_elided_lifetimes(_: &u8, _: &u8) {} @@ -28,5 +28,5 @@ LL | async fn multiple_elided_lifetimes(_: &u8, _: &u8) {} error: aborting due to 3 previous errors -Some errors occurred: E0106, E0703, E0704. +Some errors occurred: E0106, E0725, E0726. For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/no-args-non-move-async-closure.stderr b/src/test/ui/no-args-non-move-async-closure.stderr index 1e49cb2e93c..34cd0069c04 100644 --- a/src/test/ui/no-args-non-move-async-closure.stderr +++ b/src/test/ui/no-args-non-move-async-closure.stderr @@ -1,4 +1,4 @@ -error[E0705]: `async` non-`move` closures with arguments are not currently supported +error[E0727]: `async` non-`move` closures with arguments are not currently supported --> $DIR/no-args-non-move-async-closure.rs:16:13 | LL | let _ = async |x: u8| {}; @@ -8,4 +8,4 @@ LL | let _ = async |x: u8| {}; error: aborting due to previous error -For more information about this error, try `rustc --explain E0705`. +For more information about this error, try `rustc --explain E0727`. -- cgit 1.4.1-3-g733a5 From 9a310abf795a719ed816ab012bfdd23617239180 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Fri, 22 Jun 2018 16:08:07 -0700 Subject: Remove impl trait names and move bits of await into a function --- src/librustc/hir/lowering.rs | 24 +++++++----------------- src/libstd/future.rs | 30 ++++++++++++++++++++---------- src/libstd/macros.rs | 4 +--- 3 files changed, 28 insertions(+), 30 deletions(-) (limited to 'src/libstd') diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index aeef93a1740..d6da2fce69a 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -877,7 +877,7 @@ impl<'a> LoweringContext<'a> { let unstable_span = self.allow_internal_unstable(CompilerDesugaringKind::Async, span); let gen_future = self.expr_std_path( - unstable_span, &["future", "future_from_generator"], None, ThinVec::new()); + unstable_span, &["future", "from_generator"], None, ThinVec::new()); hir::ExprCall(P(gen_future), hir_vec![generator]) } @@ -1173,11 +1173,8 @@ impl<'a> LoweringContext<'a> { let span = t.span; match itctx { ImplTraitContext::Existential(fn_def_id) => { - // Set the name to `impl Bound1 + Bound2` - let exist_ty_name = Symbol::intern(&pprust::ty_to_string(t)); self.lower_existential_impl_trait( - span, fn_def_id, exist_ty_name, - |this| this.lower_param_bounds(bounds, itctx)) + span, fn_def_id, |this| this.lower_param_bounds(bounds, itctx)) } ImplTraitContext::Universal(def_id) => { let def_node_id = self.next_id().node_id; @@ -1245,7 +1242,6 @@ impl<'a> LoweringContext<'a> { &mut self, span: Span, fn_def_id: DefId, - exist_ty_name: Name, lower_bounds: impl FnOnce(&mut LoweringContext) -> hir::GenericBounds, ) -> hir::Ty_ { // We need to manually repeat the code of `next_id` because the lowering @@ -1307,7 +1303,7 @@ impl<'a> LoweringContext<'a> { let exist_ty_item = hir::Item { id: exist_ty_id.node_id, hir_id: exist_ty_id.hir_id, - name: exist_ty_name, + name: keywords::Invalid.name(), attrs: Default::default(), node: exist_ty_item_kind, vis: hir::Visibility::Inherited, @@ -2090,19 +2086,13 @@ impl<'a> LoweringContext<'a> { lifetime_collector.output_lifetime }; - let output_ty_name_owned; - let (output_ty_name, span) = match output { - FunctionRetTy::Ty(ty) => { - output_ty_name_owned = pprust::ty_to_string(ty); - (&*output_ty_name_owned, ty.span) - }, - FunctionRetTy::Default(span) => ("()", *span), + let span = match output { + FunctionRetTy::Ty(ty) => ty.span, + FunctionRetTy::Default(span) => *span, }; - // FIXME(cramertj) add lifetimes (see FIXME below) to the name - let exist_ty_name = Symbol::intern(&format!("impl Future", output_ty_name)); let impl_trait_ty = self.lower_existential_impl_trait( - span, fn_def_id, exist_ty_name, |this| { + span, fn_def_id, |this| { let output_ty = match output { FunctionRetTy::Ty(ty) => this.lower_ty(ty, ImplTraitContext::Existential(fn_def_id)), diff --git a/src/libstd/future.rs b/src/libstd/future.rs index abacb862656..2da775fdc94 100644 --- a/src/libstd/future.rs +++ b/src/libstd/future.rs @@ -26,7 +26,7 @@ pub use core::future::*; /// 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>(x: T) -> impl Future { +pub fn from_generator>(x: T) -> impl Future { GenFuture(x) } @@ -71,19 +71,22 @@ 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 + tls_cx.replace(NonNull::new( + cx + as *mut task::Context + as *mut () + as *mut task::Context<'static> + )) }); let _reset_cx = SetOnDrop(old_cx); - let res = f(); - res + f() } #[unstable(feature = "gen_future", issue = "50547")] /// Retrieves the thread-local task context used by async/await futures. /// +/// This function acquires exclusive access to the task context. +/// /// Panics if no task has been set or if the task context has already been /// retrived by a surrounding call to get_task_cx. pub fn get_task_cx(f: F) -> R @@ -91,11 +94,9 @@ 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 + tls_cx.replace(None) }); let _reset_cx = SetOnDrop(cx_ptr); @@ -104,3 +105,12 @@ where Please file an issue on https://github.com/rust-lang/rust."); unsafe { f(cx_ptr.as_mut()) } } + +#[unstable(feature = "gen_future", issue = "50547")] +/// Polls a future in the current thread-local task context. +pub fn poll_in_task_cx(f: &mut PinMut) -> Poll +where + F: Future +{ + get_task_cx(|cx| f.reborrow().poll(cx)) +} diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 1e9da42d40d..a856e7736fb 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -222,9 +222,7 @@ macro_rules! await { let mut pinned = $e; let mut pinned = unsafe { $crate::mem::PinMut::new_unchecked(&mut pinned) }; loop { - match $crate::future::get_task_cx(|cx| - $crate::future::Future::poll(pinned.reborrow(), cx)) - { + match $crate::future::poll_in_task_cx(&mut pinned) { // FIXME(cramertj) prior to stabilizing await, we have to ensure that this // can't be used to create a generator on stable via `|| await!()`. $crate::task::Poll::Pending => yield, -- cgit 1.4.1-3-g733a5