diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:03 +0000 |
commit | 64d98f8ee037282c35007b64c2649055c56af1db (patch) | |
tree | 5492bcf97fce41ee1c0b1cc2add283f3e66cdab0 /src/test/ui/let-else/let-else-drop-order.rs | |
parent | Adding debian version 1.67.1+dfsg1-1. (diff) | |
download | rustc-64d98f8ee037282c35007b64c2649055c56af1db.tar.xz rustc-64d98f8ee037282c35007b64c2649055c56af1db.zip |
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/test/ui/let-else/let-else-drop-order.rs')
-rw-r--r-- | src/test/ui/let-else/let-else-drop-order.rs | 270 |
1 files changed, 0 insertions, 270 deletions
diff --git a/src/test/ui/let-else/let-else-drop-order.rs b/src/test/ui/let-else/let-else-drop-order.rs deleted file mode 100644 index e91e5de84..000000000 --- a/src/test/ui/let-else/let-else-drop-order.rs +++ /dev/null @@ -1,270 +0,0 @@ -// run-pass -// edition:2021 -// check-run-results -// -// Drop order tests for let else -// -// Mostly this ensures two things: -// 1. That let and let else temporary drop order is the same. -// This is a specific design request: https://github.com/rust-lang/rust/pull/93628#issuecomment-1047140316 -// 2. That the else block truly only runs after the -// temporaries have dropped. -// -// We also print some nice tables for an overview by humans. -// Changes in those tables are considered breakages, but the -// important properties 1 and 2 are also enforced by the code. -// This is important as it's easy to update the stdout file -// with a --bless and miss the impact of that change. - - -#![allow(irrefutable_let_patterns)] - -use std::cell::RefCell; -use std::rc::Rc; - -#[derive(Clone)] -struct DropAccountant(Rc<RefCell<Vec<Vec<String>>>>); - -impl DropAccountant { - fn new() -> Self { - Self(Default::default()) - } - fn build_droppy(&self, v: u32) -> Droppy<u32> { - Droppy(self.clone(), v) - } - fn build_droppy_enum_none(&self, _v: u32) -> ((), DroppyEnum<u32>) { - ((), DroppyEnum::None(self.clone())) - } - fn new_list(&self, s: impl ToString) { - self.0.borrow_mut().push(vec![s.to_string()]); - } - fn push(&self, s: impl ToString) { - let s = s.to_string(); - let mut accounts = self.0.borrow_mut(); - accounts.last_mut().unwrap().push(s); - } - fn print_table(&self) { - println!(); - - let accounts = self.0.borrow(); - let before_last = &accounts[accounts.len() - 2]; - let last = &accounts[accounts.len() - 1]; - let before_last = get_comma_list(before_last); - let last = get_comma_list(last); - const LINES: &[&str] = &[ - "vanilla", - "&", - "&mut", - "move", - "fn(this)", - "tuple", - "array", - "ref &", - "ref mut &mut", - ]; - let max_len = LINES.iter().map(|v| v.len()).max().unwrap(); - let max_len_before = before_last.iter().map(|v| v.len()).max().unwrap(); - let max_len_last = last.iter().map(|v| v.len()).max().unwrap(); - - println!( - "| {: <max_len$} | {: <max_len_before$} | {: <max_len_last$} |", - "construct", before_last[0], last[0] - ); - println!("| {:-<max_len$} | {:-<max_len_before$} | {:-<max_len_last$} |", "", "", ""); - - for ((l, l_before), l_last) in - LINES.iter().zip(before_last[1..].iter()).zip(last[1..].iter()) - { - println!( - "| {: <max_len$} | {: <max_len_before$} | {: <max_len_last$} |", - l, l_before, l_last, - ); - } - } - #[track_caller] - fn assert_all_equal_to(&self, st: &str) { - let accounts = self.0.borrow(); - let last = &accounts[accounts.len() - 1]; - let last = get_comma_list(last); - for line in last[1..].iter() { - assert_eq!(line.trim(), st.trim()); - } - } - #[track_caller] - fn assert_equality_last_two_lists(&self) { - let accounts = self.0.borrow(); - let last = &accounts[accounts.len() - 1]; - let before_last = &accounts[accounts.len() - 2]; - for (l, b) in last[1..].iter().zip(before_last[1..].iter()) { - if !(l == b || l == "n/a" || b == "n/a") { - panic!("not equal: '{last:?}' != '{before_last:?}'"); - } - } - } -} - -fn get_comma_list(sl: &[String]) -> Vec<String> { - std::iter::once(sl[0].clone()) - .chain(sl[1..].chunks(2).map(|c| c.join(","))) - .collect::<Vec<String>>() -} - -struct Droppy<T>(DropAccountant, T); - -impl<T> Drop for Droppy<T> { - fn drop(&mut self) { - self.0.push("drop"); - } -} - -#[allow(dead_code)] -enum DroppyEnum<T> { - Some(DropAccountant, T), - None(DropAccountant), -} - -impl<T> Drop for DroppyEnum<T> { - fn drop(&mut self) { - match self { - DroppyEnum::Some(acc, _inner) => acc, - DroppyEnum::None(acc) => acc, - } - .push("drop"); - } -} - -macro_rules! nestings_with { - ($construct:ident, $binding:pat, $exp:expr) => { - // vanilla: - $construct!($binding, $exp.1); - - // &: - $construct!(&$binding, &$exp.1); - - // &mut: - $construct!(&mut $binding, &mut ($exp.1)); - - { - // move: - let w = $exp; - $construct!( - $binding, - { - let w = w; - w - } - .1 - ); - } - - // fn(this): - $construct!($binding, std::convert::identity($exp).1); - }; -} - -macro_rules! nestings { - ($construct:ident, $binding:pat, $exp:expr) => { - nestings_with!($construct, $binding, $exp); - - // tuple: - $construct!(($binding, 77), ($exp.1, 77)); - - // array: - $construct!([$binding], [$exp.1]); - }; -} - -macro_rules! let_else { - ($acc:expr, $v:expr, $binding:pat, $build:ident) => { - let acc = $acc; - let v = $v; - - macro_rules! let_else_construct { - ($arg:pat, $exp:expr) => { - loop { - let $arg = $exp else { - acc.push("else"); - break; - }; - acc.push("body"); - break; - } - }; - } - nestings!(let_else_construct, $binding, acc.$build(v)); - // ref &: - let_else_construct!($binding, &acc.$build(v).1); - - // ref mut &mut: - let_else_construct!($binding, &mut acc.$build(v).1); - }; -} - -macro_rules! let_ { - ($acc:expr, $binding:tt) => { - let acc = $acc; - - macro_rules! let_construct { - ($arg:pat, $exp:expr) => {{ - let $arg = $exp; - acc.push("body"); - }}; - } - let v = 0; - { - nestings_with!(let_construct, $binding, acc.build_droppy(v)); - } - acc.push("n/a"); - acc.push("n/a"); - acc.push("n/a"); - acc.push("n/a"); - - // ref &: - let_construct!($binding, &acc.build_droppy(v).1); - - // ref mut &mut: - let_construct!($binding, &mut acc.build_droppy(v).1); - }; -} - -fn main() { - let acc = DropAccountant::new(); - - println!(" --- matching cases ---"); - - // Ensure that let and let else have the same behaviour - acc.new_list("let _"); - let_!(&acc, _); - acc.new_list("let else _"); - let_else!(&acc, 0, _, build_droppy); - acc.assert_equality_last_two_lists(); - acc.print_table(); - - // Ensure that let and let else have the same behaviour - acc.new_list("let _v"); - let_!(&acc, _v); - acc.new_list("let else _v"); - let_else!(&acc, 0, _v, build_droppy); - acc.assert_equality_last_two_lists(); - acc.print_table(); - - println!(); - - println!(" --- mismatching cases ---"); - - acc.new_list("let else _ mismatch"); - let_else!(&acc, 1, DroppyEnum::Some(_, _), build_droppy_enum_none); - acc.new_list("let else _v mismatch"); - let_else!(&acc, 1, DroppyEnum::Some(_, _v), build_droppy_enum_none); - acc.print_table(); - // This ensures that we always drop before visiting the else case - acc.assert_all_equal_to("drop,else"); - - acc.new_list("let else 0 mismatch"); - let_else!(&acc, 1, 0, build_droppy); - acc.new_list("let else 0 mismatch"); - let_else!(&acc, 1, 0, build_droppy); - acc.print_table(); - // This ensures that we always drop before visiting the else case - acc.assert_all_equal_to("drop,else"); -} |