diff options
| author | bors <bors@rust-lang.org> | 2021-12-03 19:29:21 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-12-03 19:29:21 +0000 |
| commit | 532d2b14c05f9bc20b2d27cbb5f4550d28343a36 (patch) | |
| tree | f5cd6b242f405ec86b164ecfe8faf283d064ea75 | |
| parent | ff2439b7b9bafcfdff86b7847128014699df8442 (diff) | |
| parent | 3268bf1d31227d0422c90b2259e67ba12ed19e3f (diff) | |
| download | rust-532d2b14c05f9bc20b2d27cbb5f4550d28343a36.tar.gz rust-532d2b14c05f9bc20b2d27cbb5f4550d28343a36.zip | |
Auto merge of #90737 - eholk:intofuture, r=tmandry
Reintroduce `into_future` in `.await` desugaring This is a reintroduction of the remaining parts from https://github.com/rust-lang/rust/pull/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`
| -rw-r--r-- | compiler/rustc_ast_lowering/src/expr.rs | 24 | ||||
| -rw-r--r-- | compiler/rustc_ast_lowering/src/lib.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/lang_items.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_span/src/symbol.rs | 2 | ||||
| -rw-r--r-- | library/core/src/future/future.rs | 6 | ||||
| -rw-r--r-- | library/core/src/future/into_future.rs | 1 | ||||
| -rw-r--r-- | src/test/ui/async-await/async-error-span.stderr | 1 | ||||
| -rw-r--r-- | src/test/ui/async-await/async-fn-size-moved-locals.rs | 6 | ||||
| -rw-r--r-- | src/test/ui/async-await/await-into-future.rs | 30 | ||||
| -rw-r--r-- | src/test/ui/async-await/issue-70594.stderr | 2 | ||||
| -rw-r--r-- | src/test/ui/async-await/issues/issue-62009-1.stderr | 2 | ||||
| -rw-r--r-- | src/test/ui/async-await/unresolved_type_param.rs | 8 | ||||
| -rw-r--r-- | src/test/ui/async-await/unresolved_type_param.stderr | 26 | ||||
| -rw-r--r-- | src/test/ui/issues-71798.stderr | 1 | ||||
| -rw-r--r-- | src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr | 2 |
15 files changed, 105 insertions, 9 deletions
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 9c579209fe5..c9578c2f50f 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -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), @@ -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) = @@ -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( diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 2a246a99a70..1a4f0a26f2b 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -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 { @@ -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) } diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 05659e976dd..a03c561861e 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -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; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index dd6ce60abfb..06e4cee30ed 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -196,6 +196,7 @@ symbols! { Implied, Input, Into, + IntoFuture, IntoIterator, IoRead, IoWrite, @@ -737,6 +738,7 @@ symbols! { inout, instruction_set, intel, + into_future, into_iter, intra_doc_pointers, intrinsics, diff --git a/library/core/src/future/future.rs b/library/core/src/future/future.rs index 09d8a2aac26..6b62236b32f 100644 --- a/library/core/src/future/future.rs +++ b/library/core/src/future/future.rs @@ -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")] diff --git a/library/core/src/future/into_future.rs b/library/core/src/future/into_future.rs index 4020c254446..cac1866188e 100644 --- a/library/core/src/future/into_future.rs +++ b/library/core/src/future/into_future.rs @@ -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; } diff --git a/src/test/ui/async-await/async-error-span.stderr b/src/test/ui/async-await/async-error-span.stderr index 994bfd33ba4..2e3f8bb5256 100644 --- a/src/test/ui/async-await/async-error-span.stderr +++ b/src/test/ui/async-await/async-error-span.stderr @@ -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 diff --git a/src/test/ui/async-await/async-fn-size-moved-locals.rs b/src/test/ui/async-await/async-fn-size-moved-locals.rs index 636fafc2bc4..a603ebd6e85 100644 --- a/src/test/ui/async-await/async-fn-size-moved-locals.rs +++ b/src/test/ui/async-await/async-fn-size-moved-locals.rs @@ -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())); } diff --git a/src/test/ui/async-await/await-into-future.rs b/src/test/ui/async-await/await-into-future.rs new file mode 100644 index 00000000000..b74b1684440 --- /dev/null +++ b/src/test/ui/async-await/await-into-future.rs @@ -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()); +} diff --git a/src/test/ui/async-await/issue-70594.stderr b/src/test/ui/async-await/issue-70594.stderr index eb24040404b..ab05251526b 100644 --- a/src/test/ui/async-await/issue-70594.stderr +++ b/src/test/ui/async-await/issue-70594.stderr @@ -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 diff --git a/src/test/ui/async-await/issues/issue-62009-1.stderr b/src/test/ui/async-await/issues/issue-62009-1.stderr index e2ea72a1e61..19d6f9bc438 100644 --- a/src/test/ui/async-await/issues/issue-62009-1.stderr +++ b/src/test/ui/async-await/issues/issue-62009-1.stderr @@ -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 diff --git a/src/test/ui/async-await/unresolved_type_param.rs b/src/test/ui/async-await/unresolved_type_param.rs index d313691b388..85d868c2703 100644 --- a/src/test/ui/async-await/unresolved_type_param.rs +++ b/src/test/ui/async-await/unresolved_type_param.rs @@ -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` diff --git a/src/test/ui/async-await/unresolved_type_param.stderr b/src/test/ui/async-await/unresolved_type_param.stderr index 6b9e960ca1a..130667a49c5 100644 --- a/src/test/ui/async-await/unresolved_type_param.stderr +++ b/src/test/ui/async-await/unresolved_type_param.stderr @@ -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`. diff --git a/src/test/ui/issues-71798.stderr b/src/test/ui/issues-71798.stderr index bbcdd3e37a9..bc4dc9ebf9e 100644 --- a/src/test/ui/issues-71798.stderr +++ b/src/test/ui/issues-71798.stderr @@ -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 diff --git a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index 4759ebea0e9..766db2a8356 100644 --- a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -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 | @@ -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 | |
