-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Some local unit tests to track progress and capture interesting cases…
… as I identify them. issue-62958-c.rs was reduced from the tracing-attributes proc-macro crate. issue-62958-d.rs was reduced from the doc test attached to `AtomicPtr::from_mut_slice`. issue-62958-e.rs covers some important operational characteristics.
- Loading branch information
Showing
5 changed files
with
220 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// revisions: both_off just_prop both_on | ||
// ignore-tidy-linelength | ||
// run-pass | ||
// [both_off] compile-flags: -Z mir-enable-passes=-UpvarToLocalProp,-InlineFutureIntoFuture | ||
// [just_prop] compile-flags: -Z mir-enable-passes=+UpvarToLocalProp,-InlineFutureIntoFuture | ||
// [both_on] compile-flags: -Z mir-enable-passes=+UpvarToLocalProp,+InlineFutureIntoFuture | ||
// edition:2018 | ||
|
||
async fn wait() {} | ||
#[allow(dropping_copy_types)] | ||
async fn test(arg: [u8; 8192]) { | ||
wait().await; | ||
drop(arg); | ||
} | ||
|
||
#[cfg(both_off)] | ||
fn main() { | ||
let expected = 16000..=17000; | ||
let actual = std::mem::size_of_val(&test([0; 8192])); | ||
assert!(expected.contains(&actual)); | ||
} | ||
|
||
#[cfg(any(just_prop, both_on))] | ||
fn main() { | ||
let expected = 8192..=9999; | ||
let actual = std::mem::size_of_val(&test([0; 8192])); | ||
assert!(expected.contains(&actual)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// revisions: both_off just_prop both_on | ||
// ignore-tidy-linelength | ||
// run-pass | ||
// [both_off] compile-flags: -Z mir-enable-passes=-UpvarToLocalProp,-InlineFutureIntoFuture | ||
// [just_prop] compile-flags: -Z mir-enable-passes=+UpvarToLocalProp,-InlineFutureIntoFuture | ||
// [both_on] compile-flags: -Z mir-enable-passes=+UpvarToLocalProp,+InlineFutureIntoFuture | ||
// edition:2018 | ||
|
||
async fn test(_arg: [u8; 8192]) {} | ||
|
||
async fn use_future(fut: impl std::future::Future<Output = ()>) { | ||
fut.await | ||
} | ||
|
||
#[cfg(both_on)] | ||
fn main() { | ||
let expected = 8192..=9999; | ||
let actual = std::mem::size_of_val(&use_future(use_future(use_future(test([0; 8192]))))); | ||
assert!(expected.contains(&actual), "expected: {:?} actual: {}", expected, actual); | ||
} | ||
|
||
#[cfg(any(both_off, just_prop))] | ||
fn main() { | ||
let expected = 16000..=8192*(2*2*2*2); // O(2^n) LOL | ||
let actual = std::mem::size_of_val(&use_future(use_future(use_future(test([0; 8192]))))); | ||
assert!(expected.contains(&actual), "expected: {:?} actual: {}", expected, actual); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// revisions: both_off just_prop both_on | ||
// ignore-tidy-linelength | ||
// build-pass | ||
// [both_off] compile-flags: -Z mir-enable-passes=-UpvarToLocalProp,-InlineFutureIntoFuture | ||
// [just_prop] compile-flags: -Z mir-enable-passes=+UpvarToLocalProp,-InlineFutureIntoFuture | ||
// [both_on] compile-flags: -Z mir-enable-passes=+UpvarToLocalProp,+InlineFutureIntoFuture | ||
|
||
#![crate_type="rlib"] | ||
|
||
// FIXME: I should be able to expand the below into something that actually does | ||
// some interesting work. The crucial thing is to enforce a rule that we never | ||
// replace `_3` with `_1.0` on a place that holds a Deref. | ||
|
||
pub struct G { p: () } | ||
pub struct S { g: G } | ||
pub struct R<'a> { s: &'a S, b: () } | ||
|
||
pub fn gen_function(input: R<'_>) { | ||
let R { s, b: _b } = input; | ||
let S { g, .. } = s; | ||
let G { p: _p, .. } = g; | ||
loop { } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// revisions: both_off just_prop both_on | ||
// ignore-tidy-linelength | ||
// run-pass | ||
// [both_off] compile-flags: -Z mir-enable-passes=-UpvarToLocalProp,-InlineFutureIntoFuture | ||
// [just_prop] compile-flags: -Z mir-enable-passes=+UpvarToLocalProp,-InlineFutureIntoFuture | ||
// [both_on] compile-flags: -Z mir-enable-passes=+UpvarToLocalProp,+InlineFutureIntoFuture | ||
// edition:2018 | ||
|
||
#![feature(atomic_from_mut)] | ||
|
||
// FIXME: I should be able to reduce the below further now that I understand the | ||
// nature of the problem. (Namely, the fact that the old upvar_to_local_prop | ||
// code was ignoring locals in projections.) | ||
|
||
use std::ptr::null_mut; | ||
use std::sync::atomic::{AtomicPtr, Ordering}; | ||
|
||
fn main() { | ||
let mut some_ptrs = [null_mut::<String>(); 10]; | ||
let a = &*AtomicPtr::from_mut_slice(&mut some_ptrs); | ||
std::thread::scope(|s| { | ||
for i in 0..a.len() { | ||
s.spawn(move || { | ||
let name = Box::new(format!("thread{i}")); | ||
a[i].store(Box::into_raw(name), Ordering::Relaxed); | ||
}); | ||
} | ||
}); | ||
for p in some_ptrs { | ||
assert!(!p.is_null()); | ||
let name = unsafe { Box::from_raw(p) }; | ||
println!("Hello, {name}!"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
// revisions: both_off both_on | ||
// ignore-tidy-linelength | ||
// run-pass | ||
// [both_off] compile-flags: -Z mir-enable-passes=-UpvarToLocalProp,-InlineFutureIntoFuture | ||
// [both_on] compile-flags: -Z mir-enable-passes=+UpvarToLocalProp,+InlineFutureIntoFuture | ||
// edition:2018 | ||
|
||
use std::future::Future; | ||
|
||
async fn wait() {} | ||
|
||
fn test_shrinks_1(arg: [u8; 1000]) -> impl std::future::Future<Output=()> { | ||
async move { | ||
let mut local = arg; | ||
local[2] = 3; | ||
wait().await; | ||
assert_eq!(local[2], 3); | ||
} | ||
} | ||
|
||
fn test_noshrinks_1(mut arg: [u8; 1000]) -> impl std::future::Future<Output=()> { | ||
async move { | ||
let mut local = arg; | ||
local[2] = 3; | ||
let l2 = &mut arg; | ||
l2[2] = 4; | ||
wait().await; | ||
assert_eq!(local[2], 3); | ||
assert_eq!(l2[2], 4); | ||
} | ||
} | ||
|
||
fn test_noshrinks_2(arg: [u8; 1000]) -> impl std::future::Future<Output=()> { | ||
async move { | ||
let mut local = arg; | ||
local[2] = 1; | ||
let l2 = arg; | ||
wait().await; | ||
assert_eq!(local[2], 1); | ||
assert_eq!(l2[2], 0); | ||
} | ||
} | ||
|
||
fn test_noshrinks_3(arg: [u8; 1000]) -> impl std::future::Future<Output=()> { | ||
async move { | ||
let bor = &arg[2]; | ||
let mut local = arg; | ||
local[2] = 1; | ||
wait().await; | ||
assert_eq!(local[2], 1); | ||
assert_eq!(*bor, 0); | ||
} | ||
} | ||
|
||
#[cfg(both_on)] | ||
fn check_shrinks(which: &str, fut: impl std::future::Future<Output=()>) { | ||
let sz = std::mem::size_of_val(&fut); | ||
println!("{which}: {sz}"); | ||
assert!((1000..=1500).contains(&sz)); | ||
run_fut(fut) | ||
} | ||
|
||
fn check_no_shrinks(which: &str, fut: impl std::future::Future<Output=()>) { | ||
let sz = std::mem::size_of_val(&fut); | ||
println!("{which}: {sz}"); | ||
assert!((2000..).contains(&sz)); | ||
run_fut(fut); | ||
} | ||
|
||
#[cfg(both_on)] | ||
fn main() { | ||
check_shrinks("s1", test_shrinks_1([0; 1000])); | ||
|
||
check_no_shrinks("n1", test_noshrinks_1([0; 1000])); | ||
check_no_shrinks("n2", test_noshrinks_2([0; 1000])); | ||
check_no_shrinks("n3", test_noshrinks_3([0; 1000])); | ||
} | ||
|
||
#[cfg(both_off)] | ||
fn main() { | ||
check_no_shrinks("s1", test_shrinks_1([0; 1000])); | ||
check_no_shrinks("n1", test_noshrinks_1([0; 1000])); | ||
check_no_shrinks("n2", test_noshrinks_2([0; 1000])); | ||
check_no_shrinks("n3", test_noshrinks_3([0; 1000])); | ||
} | ||
|
||
fn run_fut<T>(fut: impl Future<Output = T>) -> T { | ||
use std::sync::Arc; | ||
use std::task::{Context, Poll, Wake, Waker}; | ||
|
||
struct MyWaker; | ||
impl Wake for MyWaker { | ||
fn wake(self: Arc<Self>) { | ||
unimplemented!() | ||
} | ||
} | ||
|
||
let waker = Waker::from(Arc::new(MyWaker)); | ||
let mut context = Context::from_waker(&waker); | ||
|
||
let mut pinned = Box::pin(fut); | ||
loop { | ||
match pinned.as_mut().poll(&mut context) { | ||
Poll::Pending => continue, | ||
Poll::Ready(v) => return v, | ||
} | ||
} | ||
} |