Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lowering: extend temporary lifetimes around await #64292

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
35 changes: 15 additions & 20 deletions src/librustc/hir/lowering/expr.rs
Expand Up @@ -507,14 +507,13 @@ impl LoweringContext<'_> {

/// Desugar `<expr>.await` into:
/// ```rust
/// {
/// let mut pinned = <expr>;
/// loop {
/// match <expr> {
/// mut pinned => loop {
/// match ::std::future::poll_with_tls_context(unsafe {
/// ::std::pin::Pin::new_unchecked(&mut pinned)
/// <::std::pin::Pin>::new_unchecked(&mut pinned)
/// }) {
/// ::std::task::Poll::Ready(result) => break result,
/// ::std::task::Poll::Pending => {},
/// ::std::task::Poll::Pending => {}
/// }
/// yield ();
/// }
Expand Down Expand Up @@ -549,21 +548,12 @@ impl LoweringContext<'_> {
self.allow_gen_future.clone(),
);

// let mut pinned = <expr>;
let expr = P(self.lower_expr(expr));
let pinned_ident = Ident::with_dummy_span(sym::pinned);
let (pinned_pat, pinned_pat_hid) = self.pat_ident_binding_mode(
span,
pinned_ident,
hir::BindingAnnotation::Mutable,
);
let pinned_let = self.stmt_let_pat(
ThinVec::new(),
span,
Some(expr),
pinned_pat,
hir::LocalSource::AwaitDesugar,
);

// ::std::future::poll_with_tls_context(unsafe {
// ::std::pin::Pin::new_unchecked(&mut pinned)
Expand Down Expand Up @@ -621,7 +611,7 @@ impl LoweringContext<'_> {
self.arm(hir_vec![pending_pat], empty_block)
};

let match_stmt = {
let inner_match_stmt = {
let match_expr = self.expr_match(
span,
poll_expr,
Expand All @@ -643,10 +633,11 @@ impl LoweringContext<'_> {

let loop_block = P(self.block_all(
span,
hir_vec![match_stmt, yield_stmt],
hir_vec![inner_match_stmt, yield_stmt],
None,
));

// loop { .. }
let loop_expr = P(hir::Expr {
hir_id: loop_hir_id,
node: hir::ExprKind::Loop(
Expand All @@ -658,10 +649,14 @@ impl LoweringContext<'_> {
attrs: ThinVec::new(),
});

hir::ExprKind::Block(
P(self.block_all(span, hir_vec![pinned_let], Some(loop_expr))),
None,
)
// mut pinned => loop { ... }
let pinned_arm = self.arm(hir_vec![pinned_pat], loop_expr);

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

fn lower_expr_closure(
Expand Down
24 changes: 12 additions & 12 deletions src/test/ui/async-await/async-fn-nonsend.stderr
Expand Up @@ -9,9 +9,9 @@ LL | assert_send(local_dropped_before_await());
|
= help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>`
= note: required because it appears within the type `impl std::fmt::Debug`
= note: required because it appears within the type `{impl std::fmt::Debug, impl std::future::Future, ()}`
= note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:21:39: 26:2 {impl std::fmt::Debug, impl std::future::Future, ()}]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:21:39: 26:2 {impl std::fmt::Debug, impl std::future::Future, ()}]>`
= note: required because it appears within the type `{impl std::fmt::Debug, fn() -> impl std::future::Future {fut}, impl std::future::Future, ()}`
= note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:21:39: 26:2 {impl std::fmt::Debug, fn() -> impl std::future::Future {fut}, impl std::future::Future, ()}]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:21:39: 26:2 {impl std::fmt::Debug, fn() -> impl std::future::Future {fut}, impl std::future::Future, ()}]>`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `impl std::future::Future`

Expand All @@ -26,9 +26,9 @@ LL | assert_send(non_send_temporary_in_match());
|
= help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>`
= note: required because it appears within the type `impl std::fmt::Debug`
= note: required because it appears within the type `{fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, ()}`
= note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:28:40: 37:2 {fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, ()}]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:28:40: 37:2 {fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, ()}]>`
= note: required because it appears within the type `{fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, fn() -> impl std::future::Future {fut}, impl std::future::Future, ()}`
= note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:28:40: 37:2 {fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, fn() -> impl std::future::Future {fut}, impl std::future::Future, ()}]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:28:40: 37:2 {fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, fn() -> impl std::future::Future {fut}, impl std::future::Future, ()}]>`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `impl std::future::Future`

Expand All @@ -45,9 +45,9 @@ LL | assert_send(non_sync_with_method_call());
= note: required because of the requirements on the impl of `std::marker::Send` for `&mut dyn std::fmt::Write`
= note: required because it appears within the type `std::fmt::Formatter<'_>`
= note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>`
= note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}`
= note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]>`
= note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, fn() -> impl std::future::Future {fut}, impl std::future::Future, ()}`
= note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, fn() -> impl std::future::Future {fut}, impl std::future::Future, ()}]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, fn() -> impl std::future::Future {fut}, impl std::future::Future, ()}]>`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `impl std::future::Future`

Expand All @@ -68,9 +68,9 @@ LL | assert_send(non_sync_with_method_call());
= note: required because of the requirements on the impl of `std::marker::Send` for `std::slice::Iter<'_, std::fmt::ArgumentV1<'_>>`
= note: required because it appears within the type `std::fmt::Formatter<'_>`
= note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>`
= note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}`
= note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]>`
= note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, fn() -> impl std::future::Future {fut}, impl std::future::Future, ()}`
= note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, fn() -> impl std::future::Future {fut}, impl std::future::Future, ()}]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, fn() -> impl std::future::Future {fut}, impl std::future::Future, ()}]>`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `impl std::future::Future`

Expand Down
@@ -0,0 +1,19 @@
// check-pass
// edition:2018

struct Test(String);

impl Test {
async fn borrow_async(&self) {}

fn with(&mut self, s: &str) -> &mut Self {
self.0 = s.into();
self
}
}

async fn test() {
Test("".to_string()).with("123").borrow_async().await;
}

fn main() { }
@@ -0,0 +1,12 @@
// check-pass
// edition:2018

async fn foo(x: &[Vec<u32>]) -> u32 {
0
}

async fn bar() {
foo(&[vec![123]]).await;
}

fn main() { }