1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
//@ aux-build:block-on.rs
//@ edition:2021
//@ run-pass
//@ check-run-results
//@ revisions: call call_once force_once
// call - Call the closure regularly.
// call_once - Call the closure w/ `AsyncFnOnce`, so exercising the by_move shim.
// force_once - Force the closure mode to `FnOnce`, so exercising what was fixed
// in <https://github.com/rust-lang/rust/pull/123350>.
#![allow(unused_mut)]
extern crate block_on;
#[cfg(any(call, force_once))]
macro_rules! call {
($c:expr) => { ($c)() }
}
#[cfg(call_once)]
async fn call_once(f: impl AsyncFnOnce()) {
f().await
}
#[cfg(call_once)]
macro_rules! call {
($c:expr) => { call_once($c) }
}
#[cfg(not(force_once))]
macro_rules! guidance {
($c:expr) => { $c }
}
#[cfg(force_once)]
fn infer_fnonce(c: impl AsyncFnOnce()) -> impl AsyncFnOnce() { c }
#[cfg(force_once)]
macro_rules! guidance {
($c:expr) => { infer_fnonce($c) }
}
#[derive(Debug)]
struct Drop(&'static str);
impl std::ops::Drop for Drop {
fn drop(&mut self) {
println!("{}", self.0);
}
}
struct S {
a: i32,
b: Drop,
c: Drop,
}
async fn async_main() {
// Precise capture struct
{
let mut s = S { a: 1, b: Drop("fix me up"), c: Drop("untouched") };
let mut c = guidance!(async || {
s.a = 2;
let w = &mut s.b;
w.0 = "fixed";
});
s.c.0 = "uncaptured";
let fut = call!(c);
println!("after call");
fut.await;
println!("after await");
}
println!();
// Precise capture &mut struct
{
let s = &mut S { a: 1, b: Drop("fix me up"), c: Drop("untouched") };
let mut c = guidance!(async || {
s.a = 2;
let w = &mut s.b;
w.0 = "fixed";
});
s.c.0 = "uncaptured";
let fut = call!(c);
println!("after call");
fut.await;
println!("after await");
}
println!();
// Precise capture struct by move
{
let mut s = S { a: 1, b: Drop("fix me up"), c: Drop("untouched") };
let mut c = guidance!(async move || {
s.a = 2;
let w = &mut s.b;
w.0 = "fixed";
});
s.c.0 = "uncaptured";
let fut = call!(c);
println!("after call");
fut.await;
println!("after await");
}
println!();
// Precise capture &mut struct by move
{
let s = &mut S { a: 1, b: Drop("fix me up"), c: Drop("untouched") };
let mut c = guidance!(async move || {
s.a = 2;
let w = &mut s.b;
w.0 = "fixed";
});
// `s` is still captured fully as `&mut S`.
let fut = call!(c);
println!("after call");
fut.await;
println!("after await");
}
println!();
// Precise capture struct, consume field
{
let mut s = S { a: 1, b: Drop("drop first"), c: Drop("untouched") };
let c = guidance!(async move || {
s.a = 2;
drop(s.b);
});
s.c.0 = "uncaptured";
let fut = call!(c);
println!("after call");
fut.await;
println!("after await");
}
println!();
// Precise capture struct by move, consume field
{
let mut s = S { a: 1, b: Drop("drop first"), c: Drop("untouched") };
let c = guidance!(async move || {
s.a = 2;
drop(s.b);
});
s.c.0 = "uncaptured";
let fut = call!(c);
println!("after call");
fut.await;
println!("after await");
}
}
fn main() {
block_on::block_on(async_main());
}
|