diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-07-11 04:33:14 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-07-11 04:33:14 +0200 |
| commit | 8fe7ed02d5a88839ec832d36899822d431725942 (patch) | |
| tree | 6be24121f080b8d55513201227afd6245ff738ec /src/test/ui | |
| parent | 618fc02fac7128d7372f85c7fa7cebf7b79c5fe7 (diff) | |
| parent | 128143c4e505aae88b7c6cde38aa7dab19e1e47c (diff) | |
Rollup merge of #62270 - agnxy:move-async-test, r=Centril,tmandry
Move async-await tests from run-pass to ui fix #62236 r? @Centril
Diffstat (limited to 'src/test/ui')
| -rw-r--r-- | src/test/ui/async-await/async-fn-size-moved-locals.rs | 101 | ||||
| -rw-r--r-- | src/test/ui/async-await/async-fn-size.rs | 107 | ||||
| -rw-r--r-- | src/test/ui/async-await/futures-api.rs | 61 | ||||
| -rw-r--r-- | src/test/ui/async-await/issue-60709.rs | 30 |
4 files changed, 299 insertions, 0 deletions
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 new file mode 100644 index 00000000000..d0d4eb032fc --- /dev/null +++ b/src/test/ui/async-await/async-fn-size-moved-locals.rs @@ -0,0 +1,101 @@ +// Test that we don't duplicate storage for futures moved around in .await, and +// for futures moved into other futures. +// +// The exact sizes can change by a few bytes (we'd like to know when they do). +// What we don't want to see is the wrong multiple of 1024 (the size of BigFut) +// being reflected in the size. +// +// See issue #59123 for a full explanation. + +// ignore-wasm32-bare (sizes don't match) +// run-pass + +// edition:2018 + +#![feature(async_await)] + +use std::future::Future; +use std::pin::Pin; +use std::task::{Context, Poll}; + +const BIG_FUT_SIZE: usize = 1024; +struct BigFut([u8; BIG_FUT_SIZE]); + +impl BigFut { + fn new() -> Self { + BigFut([0; BIG_FUT_SIZE]) + } } + +impl Drop for BigFut { + fn drop(&mut self) {} +} + +impl Future for BigFut { + type Output = (); + + fn poll(self: Pin<&mut Self>, _ctx: &mut Context<'_>) -> Poll<Self::Output> { + Poll::Ready(()) + } +} + +#[allow(dead_code)] +struct Joiner { + a: Option<BigFut>, + b: Option<BigFut>, + c: Option<BigFut>, +} + +impl Future for Joiner { + type Output = (); + + fn poll(self: Pin<&mut Self>, _ctx: &mut Context<'_>) -> Poll<Self::Output> { + Poll::Ready(()) + } +} + +fn noop() {} + +async fn single() { + let x = BigFut::new(); + x.await; +} + +async fn single_with_noop() { + let x = BigFut::new(); + noop(); + x.await; +} + +async fn joined() { + let a = BigFut::new(); + let b = BigFut::new(); + let c = BigFut::new(); + + let joiner = Joiner { + a: Some(a), + b: Some(b), + c: Some(c), + }; + joiner.await +} + +async fn joined_with_noop() { + let a = BigFut::new(); + let b = BigFut::new(); + let c = BigFut::new(); + + let joiner = Joiner { + a: Some(a), + b: Some(b), + c: Some(c), + }; + noop(); + joiner.await +} + +fn main() { + assert_eq!(1028, std::mem::size_of_val(&single())); + assert_eq!(1032, std::mem::size_of_val(&single_with_noop())); + assert_eq!(3084, std::mem::size_of_val(&joined())); + assert_eq!(3084, std::mem::size_of_val(&joined_with_noop())); +} diff --git a/src/test/ui/async-await/async-fn-size.rs b/src/test/ui/async-await/async-fn-size.rs new file mode 100644 index 00000000000..c6b2ed13b0a --- /dev/null +++ b/src/test/ui/async-await/async-fn-size.rs @@ -0,0 +1,107 @@ +// run-pass +// aux-build:arc_wake.rs +// edition:2018 + +#![feature(async_await)] + +extern crate arc_wake; + +use std::pin::Pin; +use std::future::Future; +use std::sync::{ + Arc, + atomic::{self, AtomicUsize}, +}; +use std::task::{Context, Poll}; +use arc_wake::ArcWake; + +struct Counter { + wakes: AtomicUsize, +} + +impl ArcWake for Counter { + fn wake(self: Arc<Self>) { + Self::wake_by_ref(&self) + } + fn wake_by_ref(arc_self: &Arc<Self>) { + arc_self.wakes.fetch_add(1, atomic::Ordering::SeqCst); + } +} + +struct WakeOnceThenComplete(bool, u8); + +impl Future for WakeOnceThenComplete { + type Output = u8; + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<u8> { + if self.0 { + Poll::Ready(self.1) + } else { + cx.waker().wake_by_ref(); + self.0 = true; + Poll::Pending + } + } +} + +fn wait(fut: impl Future<Output = u8>) -> u8 { + let mut fut = Box::pin(fut); + let counter = Arc::new(Counter { wakes: AtomicUsize::new(0) }); + let waker = ArcWake::into_waker(counter.clone()); + let mut cx = Context::from_waker(&waker); + loop { + match fut.as_mut().poll(&mut cx) { + Poll::Ready(out) => return out, + Poll::Pending => (), + } + } +} + +fn base() -> WakeOnceThenComplete { WakeOnceThenComplete(false, 1) } + +async fn await1_level1() -> u8 { + base().await +} + +async fn await2_level1() -> u8 { + base().await + base().await +} + +async fn await3_level1() -> u8 { + base().await + base().await + base().await +} + +async fn await3_level2() -> u8 { + await3_level1().await + await3_level1().await + await3_level1().await +} + +async fn await3_level3() -> u8 { + await3_level2().await + await3_level2().await + await3_level2().await +} + +async fn await3_level4() -> u8 { + await3_level3().await + await3_level3().await + await3_level3().await +} + +async fn await3_level5() -> u8 { + await3_level4().await + await3_level4().await + await3_level4().await +} + +fn main() { + assert_eq!(2, std::mem::size_of_val(&base())); + assert_eq!(8, std::mem::size_of_val(&await1_level1())); + assert_eq!(12, std::mem::size_of_val(&await2_level1())); + assert_eq!(12, std::mem::size_of_val(&await3_level1())); + assert_eq!(20, std::mem::size_of_val(&await3_level2())); + assert_eq!(28, std::mem::size_of_val(&await3_level3())); + assert_eq!(36, std::mem::size_of_val(&await3_level4())); + assert_eq!(44, std::mem::size_of_val(&await3_level5())); + + assert_eq!(1, wait(base())); + assert_eq!(1, wait(await1_level1())); + assert_eq!(2, wait(await2_level1())); + assert_eq!(3, wait(await3_level1())); + assert_eq!(9, wait(await3_level2())); + assert_eq!(27, wait(await3_level3())); + assert_eq!(81, wait(await3_level4())); + assert_eq!(243, wait(await3_level5())); +} diff --git a/src/test/ui/async-await/futures-api.rs b/src/test/ui/async-await/futures-api.rs new file mode 100644 index 00000000000..a7da058de30 --- /dev/null +++ b/src/test/ui/async-await/futures-api.rs @@ -0,0 +1,61 @@ +// run-pass + +// aux-build:arc_wake.rs + +extern crate arc_wake; + +use std::future::Future; +use std::pin::Pin; +use std::sync::{ + Arc, + atomic::{self, AtomicUsize}, +}; +use std::task::{ + Context, Poll, +}; +use arc_wake::ArcWake; + +struct Counter { + wakes: AtomicUsize, +} + +impl ArcWake for Counter { + fn wake(self: Arc<Self>) { + Self::wake_by_ref(&self) + } + fn wake_by_ref(arc_self: &Arc<Self>) { + arc_self.wakes.fetch_add(1, atomic::Ordering::SeqCst); + } +} + +struct MyFuture; + +impl Future for MyFuture { + type Output = (); + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { + // Wake twice + let waker = cx.waker(); + waker.wake_by_ref(); + waker.wake_by_ref(); + Poll::Ready(()) + } +} + +fn test_waker() { + let counter = Arc::new(Counter { + wakes: AtomicUsize::new(0), + }); + let waker = ArcWake::into_waker(counter.clone()); + assert_eq!(2, Arc::strong_count(&counter)); + { + let mut context = Context::from_waker(&waker); + assert_eq!(Poll::Ready(()), Pin::new(&mut MyFuture).poll(&mut context)); + assert_eq!(2, counter.wakes.load(atomic::Ordering::SeqCst)); + } + drop(waker); + assert_eq!(1, Arc::strong_count(&counter)); +} + +fn main() { + test_waker(); +} diff --git a/src/test/ui/async-await/issue-60709.rs b/src/test/ui/async-await/issue-60709.rs new file mode 100644 index 00000000000..ad0b49fa4a2 --- /dev/null +++ b/src/test/ui/async-await/issue-60709.rs @@ -0,0 +1,30 @@ +// This used to compile the future down to ud2, due to uninhabited types being +// handled incorrectly in generators. +// compile-flags: -Copt-level=z -Cdebuginfo=2 --edition=2018 + +// run-pass + +#![feature(async_await)] +#![allow(unused)] + +use std::future::Future; +use std::task::Poll; +use std::task::Context; +use std::pin::Pin; +use std::rc::Rc; + +struct Never(); +impl Future for Never { + type Output = (); + fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> { + Poll::Pending + } +} + +fn main() { + let fut = async { + let _rc = Rc::new(()); // Also crashes with Arc + Never().await; + }; + let _bla = fut; // Moving the future is required. +} |
