Skip to content

Commit

Permalink
Reintroduce into_future in .await desugaring
Browse files Browse the repository at this point in the history
This is a reintroduction of the remaining parts from
rust-lang#65244 that have not been relanded
yet.

Issues rust-langGH-67644, rust-langGH-67982
  • Loading branch information
eholk committed Nov 22, 2021
1 parent 936f260 commit dfa0db5
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 9 deletions.
26 changes: 21 additions & 5 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> {
// mut pinned => loop { .. }
// `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 expr = self.lower_expr_mut(expr);
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 @@ -347,6 +347,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 @@ -734,6 +735,7 @@ symbols! {
inout,
instruction_set,
intel,
into_future,
into_iter,
intra_doc_pointers,
intrinsics,
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
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()));
}
28 changes: 28 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,28 @@
// check-pass

// edition:2021

#![feature(into_future)]

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() {}
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`.

0 comments on commit dfa0db5

Please sign in to comment.