diff options
| author | bors <bors@rust-lang.org> | 2019-09-17 18:23:30 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2019-09-17 18:23:30 +0000 |
| commit | 7efe1c6e678a263b9464f2e7f06f552b4d4db5a5 (patch) | |
| tree | 661b25cd2917b50d931ac4576fedd7da26a96ca0 /src/test | |
| parent | 9150f844e2624eb013ec78ca08c1d416e6644026 (diff) | |
| parent | 2d8b10f63c394c99f2268de3132086bc72ee5a2b (diff) | |
Auto merge of #64525 - nikomatsakis:issue-64512-drop-order-tail-temp, r=davidtwco
adjust desugaring for async fn to correct drop order
Old desugaring, given a user function body `{ $stmts; $expr }`
```
{
let $param_pattern0 = $raw_param0;
...
let $param_patternN = $raw_paramN;
$stmts;
$expr
}
```
New desugaring:
```
{
let $param_pattern0 = $raw_param0;
...
let $param_patternN = $raw_paramN;
drop-temps {
$stmts;
$expr
}
}
```
The drop-temps is an internal bit of HIR that drops temporaries from the resulting expression, but it should be equivalent to `return { $stmts; $expr }`.
Fixes #64512
Fixes #64391
Diffstat (limited to 'src/test')
| -rw-r--r-- | src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs | 95 | ||||
| -rw-r--r-- | src/test/ui/async-await/issue-64391.rs | 14 |
2 files changed, 109 insertions, 0 deletions
diff --git a/src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs b/src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs new file mode 100644 index 00000000000..e40acff6dc1 --- /dev/null +++ b/src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs @@ -0,0 +1,95 @@ +// aux-build:arc_wake.rs +// edition:2018 +// run-pass + +#![allow(unused_variables)] + +// Test the drop order for parameters relative to local variables and +// temporaries created in the tail return expression of the function +// body. In particular, check that this drop order is the same between +// a `async fn` and an ordinary `fn`. See #64512. + +extern crate arc_wake; + +use arc_wake::ArcWake; +use std::cell::RefCell; +use std::future::Future; +use std::sync::Arc; +use std::rc::Rc; +use std::task::Context; + +struct EmptyWaker; + +impl ArcWake for EmptyWaker { + fn wake(self: Arc<Self>) {} +} + +#[derive(Debug, Eq, PartialEq)] +enum DropOrder { + Function, + Val(&'static str), +} + +type DropOrderListPtr = Rc<RefCell<Vec<DropOrder>>>; + +struct D(&'static str, DropOrderListPtr); + +impl Drop for D { + fn drop(&mut self) { + self.1.borrow_mut().push(DropOrder::Val(self.0)); + } +} + +/// Check drop order of temporary "temp" as compared to `x`, `y`, and `z`. +/// +/// Expected order: +/// - `z` +/// - temp +/// - `y` +/// - `x` +async fn foo_async(x: D, _y: D) { + let l = x.1.clone(); + let z = D("z", l.clone()); + l.borrow_mut().push(DropOrder::Function); + helper_async(&D("temp", l)).await +} + +async fn helper_async(v: &D) { } + +fn foo_sync(x: D, _y: D) { + let l = x.1.clone(); + let z = D("z", l.clone()); + l.borrow_mut().push(DropOrder::Function); + helper_sync(&D("temp", l)) +} + +fn helper_sync(v: &D) { } + +fn assert_drop_order_after_poll<Fut: Future<Output = ()>>( + f: impl FnOnce(DropOrderListPtr) -> Fut, + g: impl FnOnce(DropOrderListPtr), +) { + let empty = Arc::new(EmptyWaker); + let waker = ArcWake::into_waker(empty); + let mut cx = Context::from_waker(&waker); + + let actual_order = Rc::new(RefCell::new(Vec::new())); + let mut fut = Box::pin(f(actual_order.clone())); + let r = fut.as_mut().poll(&mut cx); + + assert!(match r { + std::task::Poll::Ready(()) => true, + _ => false, + }); + + let expected_order = Rc::new(RefCell::new(Vec::new())); + g(expected_order.clone()); + + assert_eq!(*actual_order.borrow(), *expected_order.borrow()); +} + +fn main() { + // Free functions (see doc comment on function for what it tests). + assert_drop_order_after_poll(|l| foo_async(D("x", l.clone()), D("_y", l.clone())), + |l| foo_sync(D("x", l.clone()), D("_y", l.clone()))); +} diff --git a/src/test/ui/async-await/issue-64391.rs b/src/test/ui/async-await/issue-64391.rs new file mode 100644 index 00000000000..c6faad3aad0 --- /dev/null +++ b/src/test/ui/async-await/issue-64391.rs @@ -0,0 +1,14 @@ +// Regression test for Issue #64391. The goal here is that this +// function compiles. In the past, due to incorrect drop order for +// temporaries in the tail expression, we failed to compile this +// example. The drop order itself is directly tested in +// `drop-order/drop-order-for-temporary-in-tail-return-expr.rs`. +// +// check-pass +// edition:2018 + +async fn add(x: u32, y: u32) -> u32 { + async { x + y }.await +} + +fn main() { } |
