Skip to content

Commit

Permalink
Auto merge of #90737 - eholk:intofuture, r=tmandry
Browse files Browse the repository at this point in the history
Reintroduce `into_future` in `.await` desugaring

This is a reintroduction of the remaining parts from #65244 that have not been relanded yet.

This isn't quite ready to merge yet. The last attempt was reverting due to performance regressions, so we need to make sure this does not introduce those issues again.

Issues #67644, #67982

/cc `@yoshuawuyts`
  • Loading branch information
bors committed Dec 3, 2021
2 parents ff2439b + 3268bf1 commit 532d2b1
Show file tree
Hide file tree
Showing 15 changed files with 105 additions and 9 deletions.
24 changes: 20 additions & 4 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ impl<'hir> LoweringContext<'_, 'hir> {

/// Desugar `<expr>.await` into:
/// ```rust
/// match <expr> {
/// match ::std::future::IntoFuture::into_future(<expr>) {
/// mut pinned => loop {
/// match unsafe { ::std::future::Future::poll(
/// <::std::pin::Pin>::new_unchecked(&mut pinned),
Expand Down Expand Up @@ -629,7 +629,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
await_span,
self.allow_gen_future.clone(),
);
let expr = self.lower_expr(expr);
let expr = self.lower_expr_mut(expr);

let pinned_ident = Ident::with_dummy_span(sym::pinned);
let (pinned_pat, pinned_pat_hid) =
Expand Down Expand Up @@ -746,10 +746,26 @@ impl<'hir> LoweringContext<'_, 'hir> {
// mut pinned => loop { ... }
let pinned_arm = self.arm(pinned_pat, loop_expr);

// match <expr> {
// `match ::std::future::IntoFuture::into_future(<expr>) { ... }`
let into_future_span = self.mark_span_with_reason(
DesugaringKind::Await,
await_span,
self.allow_into_future.clone(),
);
let into_future_expr = self.expr_call_lang_item_fn(
into_future_span,
hir::LangItem::IntoFutureIntoFuture,
arena_vec![self; expr],
);

// match <into_future_expr> {
// mut pinned => loop { .. }
// }
hir::ExprKind::Match(expr, arena_vec![self; pinned_arm], hir::MatchSource::AwaitDesugar)
hir::ExprKind::Match(
into_future_expr,
arena_vec![self; pinned_arm],
hir::MatchSource::AwaitDesugar,
)
}

fn lower_expr_closure(
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ struct LoweringContext<'a, 'hir: 'a> {

allow_try_trait: Option<Lrc<[Symbol]>>,
allow_gen_future: Option<Lrc<[Symbol]>>,
allow_into_future: Option<Lrc<[Symbol]>>,
}

pub trait ResolverAstLowering {
Expand Down Expand Up @@ -320,6 +321,7 @@ pub fn lower_crate<'a, 'hir>(
in_scope_lifetimes: Vec::new(),
allow_try_trait: Some([sym::try_trait_v2][..].into()),
allow_gen_future: Some([sym::gen_future][..].into()),
allow_into_future: Some([sym::into_future][..].into()),
}
.lower_crate(krate)
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ language_item_table! {
ControlFlowContinue, sym::Continue, cf_continue_variant, Target::Variant, GenericRequirement::None;
ControlFlowBreak, sym::Break, cf_break_variant, Target::Variant, GenericRequirement::None;

IntoFutureIntoFuture, sym::into_future, into_future_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
IntoIterIntoIter, sym::into_iter, into_iter_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
IteratorNext, sym::next, next_fn, Target::Method(MethodKind::Trait { body: false}), GenericRequirement::None;

Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ symbols! {
Implied,
Input,
Into,
IntoFuture,
IntoIterator,
IoRead,
IoWrite,
Expand Down Expand Up @@ -737,6 +738,7 @@ symbols! {
inout,
instruction_set,
intel,
into_future,
into_iter,
intra_doc_pointers,
intrinsics,
Expand Down
6 changes: 5 additions & 1 deletion library/core/src/future/future.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ use crate::task::{Context, Poll};
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[stable(feature = "futures_api", since = "1.36.0")]
#[lang = "future_trait"]
#[rustc_on_unimplemented(label = "`{Self}` is not a future", message = "`{Self}` is not a future")]
#[rustc_on_unimplemented(
label = "`{Self}` is not a future",
message = "`{Self}` is not a future",
note = "{Self} must be a future or must implement `IntoFuture` to be awaited"
)]
pub trait Future {
/// The type of value produced on completion.
#[stable(feature = "futures_api", since = "1.36.0")]
Expand Down
1 change: 1 addition & 0 deletions library/core/src/future/into_future.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub trait IntoFuture {

/// Creates a future from a value.
#[unstable(feature = "into_future", issue = "67644")]
#[cfg_attr(not(bootstrap), lang = "into_future")]
fn into_future(self) -> Self::Future;
}

Expand Down
1 change: 1 addition & 0 deletions src/test/ui/async-await/async-error-span.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ LL | fn get_future() -> impl Future<Output = ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future
|
= help: the trait `Future` is not implemented for `()`
= note: () must be a future or must implement `IntoFuture` to be awaited

error[E0698]: type inside `async fn` body must be known in this context
--> $DIR/async-error-span.rs:13:9
Expand Down
6 changes: 3 additions & 3 deletions src/test/ui/async-await/async-fn-size-moved-locals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ async fn mixed_sizes() {
fn main() {
assert_eq!(1025, std::mem::size_of_val(&single()));
assert_eq!(1026, std::mem::size_of_val(&single_with_noop()));
assert_eq!(3078, std::mem::size_of_val(&joined()));
assert_eq!(3079, std::mem::size_of_val(&joined_with_noop()));
assert_eq!(7181, std::mem::size_of_val(&mixed_sizes()));
assert_eq!(3076, std::mem::size_of_val(&joined()));
assert_eq!(3076, std::mem::size_of_val(&joined_with_noop()));
assert_eq!(6157, std::mem::size_of_val(&mixed_sizes()));
}
30 changes: 30 additions & 0 deletions src/test/ui/async-await/await-into-future.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// run-pass
// aux-build: issue-72470-lib.rs
// edition:2021
#![feature(into_future)]

extern crate issue_72470_lib;
use std::{future::{Future, IntoFuture}, pin::Pin};

struct AwaitMe;

impl IntoFuture for AwaitMe {
type Output = i32;
type Future = Pin<Box<dyn Future<Output = i32>>>;

fn into_future(self) -> Self::Future {
Box::pin(me())
}
}

async fn me() -> i32 {
41
}

async fn run() {
assert_eq!(AwaitMe.await, 41);
}

fn main() {
issue_72470_lib::run(run());
}
2 changes: 2 additions & 0 deletions src/test/ui/async-await/issue-70594.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ LL | [1; ().await];
| ^^^^^^^^ `()` is not a future
|
= help: the trait `Future` is not implemented for `()`
= note: () must be a future or must implement `IntoFuture` to be awaited
= note: required because of the requirements on the impl of `IntoFuture` for `()`

error: aborting due to 4 previous errors

Expand Down
2 changes: 2 additions & 0 deletions src/test/ui/async-await/issues/issue-62009-1.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ LL | (|_| 2333).await;
| ^^^^^^^^^^^^^^^^ `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` is not a future
|
= help: the trait `Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]`
= note: [closure@$DIR/issue-62009-1.rs:12:5: 12:15] must be a future or must implement `IntoFuture` to be awaited
= note: required because of the requirements on the impl of `IntoFuture` for `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]`

error: aborting due to 4 previous errors

Expand Down
8 changes: 8 additions & 0 deletions src/test/ui/async-await/unresolved_type_param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,20 @@ async fn foo() {
//~^ ERROR type inside `async fn` body must be known in this context
//~| ERROR type inside `async fn` body must be known in this context
//~| ERROR type inside `async fn` body must be known in this context
//~| ERROR type inside `async fn` body must be known in this context
//~| ERROR type inside `async fn` body must be known in this context
//~| NOTE cannot infer type for type parameter `T`
//~| NOTE cannot infer type for type parameter `T`
//~| NOTE cannot infer type for type parameter `T`
//~| NOTE cannot infer type for type parameter `T`
//~| NOTE cannot infer type for type parameter `T`
//~| NOTE the type is part of the `async fn` body because of this `await`
//~| NOTE the type is part of the `async fn` body because of this `await`
//~| NOTE the type is part of the `async fn` body because of this `await`
//~| NOTE the type is part of the `async fn` body because of this `await`
//~| NOTE the type is part of the `async fn` body because of this `await`
//~| NOTE in this expansion of desugaring of `await`
//~| NOTE in this expansion of desugaring of `await`
//~| NOTE in this expansion of desugaring of `await`
//~| NOTE in this expansion of desugaring of `await`
//~| NOTE in this expansion of desugaring of `await`
Expand Down
26 changes: 25 additions & 1 deletion src/test/ui/async-await/unresolved_type_param.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,30 @@ note: the type is part of the `async fn` body because of this `await`
LL | bar().await;
| ^^^^^^^^^^^

error: aborting due to 3 previous errors
error[E0698]: type inside `async fn` body must be known in this context
--> $DIR/unresolved_type_param.rs:9:5
|
LL | bar().await;
| ^^^ cannot infer type for type parameter `T` declared on the function `bar`
|
note: the type is part of the `async fn` body because of this `await`
--> $DIR/unresolved_type_param.rs:9:5
|
LL | bar().await;
| ^^^^^^^^^^^

error[E0698]: type inside `async fn` body must be known in this context
--> $DIR/unresolved_type_param.rs:9:5
|
LL | bar().await;
| ^^^ cannot infer type for type parameter `T` declared on the function `bar`
|
note: the type is part of the `async fn` body because of this `await`
--> $DIR/unresolved_type_param.rs:9:5
|
LL | bar().await;
| ^^^^^^^^^^^

error: aborting due to 5 previous errors

For more information about this error, try `rustc --explain E0698`.
1 change: 1 addition & 0 deletions src/test/ui/issues-71798.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ LL | fn test_ref(x: &u32) -> impl std::future::Future<Output = u32> + '_ {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `u32` is not a future
|
= help: the trait `Future` is not implemented for `u32`
= note: u32 must be a future or must implement `IntoFuture` to be awaited

error: aborting due to 2 previous errors

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ LL | bar(foo);
| required by a bound introduced by this call
|
= help: the trait `Future` is not implemented for `fn() -> impl Future<Output = ()> {foo}`
= note: fn() -> impl Future<Output = ()> {foo} must be a future or must implement `IntoFuture` to be awaited
note: required by a bound in `bar`
--> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16
|
Expand All @@ -31,6 +32,7 @@ LL | bar(async_closure);
| required by a bound introduced by this call
|
= help: the trait `Future` is not implemented for `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]`
= note: [closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36] must be a future or must implement `IntoFuture` to be awaited
note: required by a bound in `bar`
--> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16
|
Expand Down

0 comments on commit 532d2b1

Please sign in to comment.