Skip to content

Commit f35517e

Browse files
committed
core: add IntoFuture trait and support for await
1 parent 41501a6 commit f35517e

File tree

10 files changed

+90
-12
lines changed

10 files changed

+90
-12
lines changed

src/libcore/future/future.rs

+25
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,21 @@ pub trait Future {
9999
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
100100
}
101101

102+
/// Conversion into a `Future`.
103+
#[unstable(feature = "into_future", issue = "67644")]
104+
pub trait IntoFuture {
105+
/// The output that the future will produce on completion.
106+
#[unstable(feature = "into_future", issue = "67644")]
107+
type Output;
108+
/// Which kind of future are we turning this into?
109+
#[unstable(feature = "into_future", issue = "67644")]
110+
type Future: Future<Output = Self::Output>;
111+
112+
/// Creates a future from a value.
113+
#[unstable(feature = "into_future", issue = "67644")]
114+
fn into_future(self) -> Self::Future;
115+
}
116+
102117
#[stable(feature = "futures_api", since = "1.36.0")]
103118
impl<F: ?Sized + Future + Unpin> Future for &mut F {
104119
type Output = F::Output;
@@ -119,3 +134,13 @@ where
119134
Pin::get_mut(self).as_mut().poll(cx)
120135
}
121136
}
137+
138+
#[unstable(feature = "into_future", issue = "67644")]
139+
impl<F: Future> IntoFuture for F {
140+
type Output = F::Output;
141+
type Future = F;
142+
143+
fn into_future(self) -> Self::Future {
144+
self
145+
}
146+
}

src/libcore/future/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@
55
mod future;
66
#[stable(feature = "futures_api", since = "1.36.0")]
77
pub use self::future::Future;
8+
9+
#[unstable(feature = "into_future", issue = "67644")]
10+
pub use self::future::IntoFuture;

src/librustc/hir/lowering.rs

+2
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ pub struct LoweringContext<'a, 'hir: 'a> {
168168

169169
allow_try_trait: Option<Lrc<[Symbol]>>,
170170
allow_gen_future: Option<Lrc<[Symbol]>>,
171+
allow_into_future: Option<Lrc<[Symbol]>>,
171172
}
172173

173174
pub trait Resolver {
@@ -300,6 +301,7 @@ pub fn lower_crate<'a, 'hir>(
300301
in_scope_lifetimes: Vec::new(),
301302
allow_try_trait: Some([sym::try_trait][..].into()),
302303
allow_gen_future: Some([sym::gen_future][..].into()),
304+
allow_into_future: Some([sym::into_future][..].into()),
303305
}
304306
.lower_crate(krate)
305307
}

src/librustc/hir/lowering/expr.rs

+20-4
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
529529

530530
/// Desugar `<expr>.await` into:
531531
/// ```rust
532-
/// match <expr> {
532+
/// match ::std::future::IntoFuture::into_future(<expr>) {
533533
/// mut pinned => loop {
534534
/// match ::std::future::poll_with_tls_context(unsafe {
535535
/// <::std::pin::Pin>::new_unchecked(&mut pinned)
@@ -653,11 +653,27 @@ impl<'hir> LoweringContext<'_, 'hir> {
653653
// mut pinned => loop { ... }
654654
let pinned_arm = self.arm(pinned_pat, loop_expr);
655655

656-
// match <expr> {
656+
// `match ::std::future::IntoFuture::into_future(<expr>) { ... }`
657+
let into_future_span = self.mark_span_with_reason(
658+
DesugaringKind::Await,
659+
await_span,
660+
self.allow_into_future.clone(),
661+
);
662+
let expr = self.lower_expr_mut(expr);
663+
let into_future_expr = self.expr_call_std_path(
664+
into_future_span,
665+
&[sym::future, sym::IntoFuture, sym::into_future],
666+
arena_vec![self; expr],
667+
);
668+
669+
// match <into_future_expr> {
657670
// mut pinned => loop { .. }
658671
// }
659-
let expr = self.lower_expr(expr);
660-
hir::ExprKind::Match(expr, arena_vec![self; pinned_arm], hir::MatchSource::AwaitDesugar)
672+
hir::ExprKind::Match(
673+
into_future_expr,
674+
arena_vec![self; pinned_arm],
675+
hir::MatchSource::AwaitDesugar,
676+
)
661677
}
662678

663679
fn lower_expr_closure(

src/libstd/future.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ use core::task::{Context, Poll};
1010

1111
#[doc(inline)]
1212
#[stable(feature = "futures_api", since = "1.36.0")]
13-
pub use core::future::*;
13+
pub use core::future::Future;
14+
15+
#[doc(inline)]
16+
#[unstable(feature = "into_future", issue = "67644")]
17+
pub use core::future::IntoFuture;
1418

1519
/// Wrap a generator in a future.
1620
///

src/libstd/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@
269269
#![feature(hashmap_internals)]
270270
#![feature(int_error_internals)]
271271
#![feature(int_error_matching)]
272+
#![feature(into_future)]
272273
#![feature(integer_atomics)]
273274
#![feature(lang_items)]
274275
#![feature(libc)]

src/libsyntax_pos/symbol.rs

+2
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,8 @@ symbols! {
379379
infer_static_outlives_requirements,
380380
inline,
381381
intel,
382+
into_future,
383+
IntoFuture,
382384
into_iter,
383385
IntoIterator,
384386
into_result,

src/test/ui/async-await/async-fn-size-moved-locals.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ async fn mixed_sizes() {
112112
fn main() {
113113
assert_eq!(1028, std::mem::size_of_val(&single()));
114114
assert_eq!(1032, std::mem::size_of_val(&single_with_noop()));
115-
assert_eq!(3084, std::mem::size_of_val(&joined()));
116-
assert_eq!(3084, std::mem::size_of_val(&joined_with_noop()));
117-
assert_eq!(7188, std::mem::size_of_val(&mixed_sizes()));
115+
assert_eq!(3080, std::mem::size_of_val(&joined()));
116+
assert_eq!(3080, std::mem::size_of_val(&joined_with_noop()));
117+
assert_eq!(6164, std::mem::size_of_val(&mixed_sizes()));
118118
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// check-pass
2+
3+
// edition:2018
4+
5+
#![feature(into_future)]
6+
7+
use std::{future::{Future, IntoFuture}, pin::Pin};
8+
9+
struct AwaitMe;
10+
11+
impl IntoFuture for AwaitMe {
12+
type Output = i32;
13+
type Future = Pin<Box<dyn Future<Output = i32>>>;
14+
15+
fn into_future(self) -> Self::Future {
16+
Box::pin(me())
17+
}
18+
}
19+
20+
async fn me() -> i32 {
21+
41
22+
}
23+
24+
async fn run() {
25+
assert_eq!(AwaitMe.await, 41);
26+
}
27+
28+
fn main() {}

src/test/ui/async-await/issues/issue-62009-1.stderr

+1-4
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,8 @@ error[E0277]: the trait bound `[closure@$DIR/issue-62009-1.rs:13:5: 13:15]: std:
3232
|
3333
LL | (|_| 2333).await;
3434
| ^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:13:5: 13:15]`
35-
|
36-
::: $SRC_DIR/libstd/future.rs:LL:COL
3735
|
38-
LL | F: Future,
39-
| ------ required by this bound in `std::future::poll_with_tls_context`
36+
= note: required by `std::future::IntoFuture::into_future`
4037

4138
error: aborting due to 4 previous errors
4239

0 commit comments

Comments
 (0)