|
| 1 | +// revisions: both_off both_on |
| 2 | +// ignore-tidy-linelength |
| 3 | +// run-pass |
| 4 | +// [both_off] compile-flags: -Z mir-enable-passes=-UpvarToLocalProp,-InlineFutureIntoFuture |
| 5 | +// [both_on] compile-flags: -Z mir-enable-passes=+UpvarToLocalProp,+InlineFutureIntoFuture |
| 6 | +// edition:2018 |
| 7 | + |
| 8 | +use std::future::Future; |
| 9 | + |
| 10 | +async fn wait() {} |
| 11 | + |
| 12 | +fn test_shrinks_1(arg: [u8; 1000]) -> impl std::future::Future<Output=()> { |
| 13 | + async move { |
| 14 | + let mut local = arg; |
| 15 | + local[2] = 3; |
| 16 | + wait().await; |
| 17 | + assert_eq!(local[2], 3); |
| 18 | + } |
| 19 | +} |
| 20 | + |
| 21 | +fn test_noshrinks_1(mut arg: [u8; 1000]) -> impl std::future::Future<Output=()> { |
| 22 | + async move { |
| 23 | + let mut local = arg; |
| 24 | + local[2] = 3; |
| 25 | + let l2 = &mut arg; |
| 26 | + l2[2] = 4; |
| 27 | + wait().await; |
| 28 | + assert_eq!(local[2], 3); |
| 29 | + assert_eq!(l2[2], 4); |
| 30 | + } |
| 31 | +} |
| 32 | + |
| 33 | +fn test_noshrinks_2(arg: [u8; 1000]) -> impl std::future::Future<Output=()> { |
| 34 | + async move { |
| 35 | + let mut local = arg; |
| 36 | + local[2] = 1; |
| 37 | + let l2 = arg; |
| 38 | + wait().await; |
| 39 | + assert_eq!(local[2], 1); |
| 40 | + assert_eq!(l2[2], 0); |
| 41 | + } |
| 42 | +} |
| 43 | + |
| 44 | +fn test_noshrinks_3(arg: [u8; 1000]) -> impl std::future::Future<Output=()> { |
| 45 | + async move { |
| 46 | + let bor = &arg[2]; |
| 47 | + let mut local = arg; |
| 48 | + local[2] = 1; |
| 49 | + wait().await; |
| 50 | + assert_eq!(local[2], 1); |
| 51 | + assert_eq!(*bor, 0); |
| 52 | + } |
| 53 | +} |
| 54 | + |
| 55 | +#[cfg(both_on)] |
| 56 | +fn check_shrinks(which: &str, fut: impl std::future::Future<Output=()>) { |
| 57 | + let sz = std::mem::size_of_val(&fut); |
| 58 | + println!("{which}: {sz}"); |
| 59 | + assert!((1000..=1500).contains(&sz)); |
| 60 | + run_fut(fut) |
| 61 | +} |
| 62 | + |
| 63 | +fn check_no_shrinks(which: &str, fut: impl std::future::Future<Output=()>) { |
| 64 | + let sz = std::mem::size_of_val(&fut); |
| 65 | + println!("{which}: {sz}"); |
| 66 | + assert!((2000..).contains(&sz)); |
| 67 | + run_fut(fut); |
| 68 | +} |
| 69 | + |
| 70 | +#[cfg(both_on)] |
| 71 | +fn main() { |
| 72 | + check_shrinks("s1", test_shrinks_1([0; 1000])); |
| 73 | + |
| 74 | + check_no_shrinks("n1", test_noshrinks_1([0; 1000])); |
| 75 | + check_no_shrinks("n2", test_noshrinks_2([0; 1000])); |
| 76 | + check_no_shrinks("n3", test_noshrinks_3([0; 1000])); |
| 77 | +} |
| 78 | + |
| 79 | +#[cfg(both_off)] |
| 80 | +fn main() { |
| 81 | + check_no_shrinks("s1", test_shrinks_1([0; 1000])); |
| 82 | + check_no_shrinks("n1", test_noshrinks_1([0; 1000])); |
| 83 | + check_no_shrinks("n2", test_noshrinks_2([0; 1000])); |
| 84 | + check_no_shrinks("n3", test_noshrinks_3([0; 1000])); |
| 85 | +} |
| 86 | + |
| 87 | +fn run_fut<T>(fut: impl Future<Output = T>) -> T { |
| 88 | + use std::sync::Arc; |
| 89 | + use std::task::{Context, Poll, Wake, Waker}; |
| 90 | + |
| 91 | + struct MyWaker; |
| 92 | + impl Wake for MyWaker { |
| 93 | + fn wake(self: Arc<Self>) { |
| 94 | + unimplemented!() |
| 95 | + } |
| 96 | + } |
| 97 | + |
| 98 | + let waker = Waker::from(Arc::new(MyWaker)); |
| 99 | + let mut context = Context::from_waker(&waker); |
| 100 | + |
| 101 | + let mut pinned = Box::pin(fut); |
| 102 | + loop { |
| 103 | + match pinned.as_mut().poll(&mut context) { |
| 104 | + Poll::Pending => continue, |
| 105 | + Poll::Ready(v) => return v, |
| 106 | + } |
| 107 | + } |
| 108 | +} |
0 commit comments