Skip to content

Commit 976ac3b

Browse files
committed
Auto merge of #68811 - tmandry:back-to-intofuture, r=<try>
Re-land "add IntoFuture trait and support for await" Testing the code from #65244 to see if the performance regressions are still there. #68606 and #68672 made perf optimizations that might interact with this change. If this lands, fixes #67982. cc @seanmonstar @jonas-schievink r? @cramertj
2 parents 8417d68 + c27d6f5 commit 976ac3b

File tree

12 files changed

+123
-13
lines changed

12 files changed

+123
-13
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_ast_lowering/expr.rs

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

522522
/// Desugar `<expr>.await` into:
523523
/// ```rust
524-
/// match <expr> {
524+
/// match ::std::future::IntoFuture::into_future(<expr>) {
525525
/// mut pinned => loop {
526526
/// match ::std::future::poll_with_tls_context(unsafe {
527527
/// <::std::pin::Pin>::new_unchecked(&mut pinned)
@@ -645,11 +645,27 @@ impl<'hir> LoweringContext<'_, 'hir> {
645645
// mut pinned => loop { ... }
646646
let pinned_arm = self.arm(pinned_pat, loop_expr);
647647

648-
// match <expr> {
648+
// `match ::std::future::IntoFuture::into_future(<expr>) { ... }`
649+
let into_future_span = self.mark_span_with_reason(
650+
DesugaringKind::Await,
651+
await_span,
652+
self.allow_into_future.clone(),
653+
);
654+
let expr = self.lower_expr_mut(expr);
655+
let into_future_expr = self.expr_call_std_path(
656+
into_future_span,
657+
&[sym::future, sym::IntoFuture, sym::into_future],
658+
arena_vec![self; expr],
659+
);
660+
661+
// match <into_future_expr> {
649662
// mut pinned => loop { .. }
650663
// }
651-
let expr = self.lower_expr(expr);
652-
hir::ExprKind::Match(expr, arena_vec![self; pinned_arm], hir::MatchSource::AwaitDesugar)
664+
hir::ExprKind::Match(
665+
into_future_expr,
666+
arena_vec![self; pinned_arm],
667+
hir::MatchSource::AwaitDesugar,
668+
)
653669
}
654670

655671
fn lower_expr_closure(

src/librustc_ast_lowering/lib.rs

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

167167
allow_try_trait: Option<Lrc<[Symbol]>>,
168168
allow_gen_future: Option<Lrc<[Symbol]>>,
169+
allow_into_future: Option<Lrc<[Symbol]>>,
169170
}
170171

171172
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_span/symbol.rs

+2
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,8 @@ symbols! {
383383
infer_static_outlives_requirements,
384384
inline,
385385
intel,
386+
into_future,
387+
IntoFuture,
386388
into_iter,
387389
IntoIterator,
388390
into_result,

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
@@ -270,6 +270,7 @@
270270
#![feature(hashmap_internals)]
271271
#![feature(int_error_internals)]
272272
#![feature(int_error_matching)]
273+
#![feature(into_future)]
273274
#![feature(integer_atomics)]
274275
#![feature(lang_items)]
275276
#![feature(libc)]

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:16:5: 16:15]: std:
3232
|
3333
LL | (|_| 2333).await;
3434
| ^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:16:5: 16: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

src/test/ui/async-await/unresolved_type_param.rs

+8
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,20 @@ async fn foo() {
1010
//~^ ERROR type inside `async fn` body must be known in this context
1111
//~| ERROR type inside `async fn` body must be known in this context
1212
//~| ERROR type inside `async fn` body must be known in this context
13+
//~| ERROR type inside `async fn` body must be known in this context
14+
//~| ERROR type inside `async fn` body must be known in this context
15+
//~| NOTE cannot infer type for type parameter `T`
16+
//~| NOTE cannot infer type for type parameter `T`
1317
//~| NOTE cannot infer type for type parameter `T`
1418
//~| NOTE cannot infer type for type parameter `T`
1519
//~| NOTE cannot infer type for type parameter `T`
1620
//~| NOTE the type is part of the `async fn` body because of this `await`
1721
//~| NOTE the type is part of the `async fn` body because of this `await`
1822
//~| NOTE the type is part of the `async fn` body because of this `await`
23+
//~| NOTE the type is part of the `async fn` body because of this `await`
24+
//~| NOTE the type is part of the `async fn` body because of this `await`
25+
//~| NOTE in this expansion of desugaring of `await`
26+
//~| NOTE in this expansion of desugaring of `await`
1927
//~| NOTE in this expansion of desugaring of `await`
2028
//~| NOTE in this expansion of desugaring of `await`
2129
//~| NOTE in this expansion of desugaring of `await`

src/test/ui/async-await/unresolved_type_param.stderr

+25-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,30 @@ note: the type is part of the `async fn` body because of this `await`
3434
LL | bar().await;
3535
| ^^^^^^^^^^^
3636

37-
error: aborting due to 3 previous errors
37+
error[E0698]: type inside `async fn` body must be known in this context
38+
--> $DIR/unresolved_type_param.rs:9:5
39+
|
40+
LL | bar().await;
41+
| ^^^ cannot infer type for type parameter `T` declared on the function `bar`
42+
|
43+
note: the type is part of the `async fn` body because of this `await`
44+
--> $DIR/unresolved_type_param.rs:9:5
45+
|
46+
LL | bar().await;
47+
| ^^^^^^^^^^^
48+
49+
error[E0698]: type inside `async fn` body must be known in this context
50+
--> $DIR/unresolved_type_param.rs:9:5
51+
|
52+
LL | bar().await;
53+
| ^^^ cannot infer type for type parameter `T` declared on the function `bar`
54+
|
55+
note: the type is part of the `async fn` body because of this `await`
56+
--> $DIR/unresolved_type_param.rs:9:5
57+
|
58+
LL | bar().await;
59+
| ^^^^^^^^^^^
60+
61+
error: aborting due to 5 previous errors
3862

3963
For more information about this error, try `rustc --explain E0698`.

0 commit comments

Comments
 (0)