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/issues/issue-23611-enum-swap-in-drop.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/issues/issue-23611-enum-swap-in-drop.rs')
-rw-r--r-- | src/test/ui/issues/issue-23611-enum-swap-in-drop.rs | 259 |
1 files changed, 0 insertions, 259 deletions
diff --git a/src/test/ui/issues/issue-23611-enum-swap-in-drop.rs b/src/test/ui/issues/issue-23611-enum-swap-in-drop.rs deleted file mode 100644 index cdb130d60..000000000 --- a/src/test/ui/issues/issue-23611-enum-swap-in-drop.rs +++ /dev/null @@ -1,259 +0,0 @@ -// run-pass -#![allow(non_upper_case_globals)] - -// Issue 23611: this test is ensuring that, for an instance `X` of the -// enum `E`, if you swap in a different variant during the execution -// of the `<E as Drop>::drop`, then the appropriate substructure will -// be torn down after the `<E as Drop>::drop` method returns. - -use std::cell::RefCell; -use std::mem; - -use self::d::D; - -pub fn main() { - let log = RefCell::new(vec![]); - d::println("created empty log"); - test(&log); - - // println!("log: {:?}", &log.borrow()[..]); - assert_eq!( - &log.borrow()[..], - [ - // created empty log - // +-- Make D(test_1, 10000000) - // | +-- Make D(g_b_5, 50000001) - // | | in g_B(b2b0) from E::drop, b=b4b0 - // | +-- Drop D(g_b_5, 50000001) - 50000001, - // | - // | +-- Make D(drop_6, 60000002) - // | | +-- Make D(g_b_5, 50000003) - // | | | in g_B(b2b0) from E::drop, b=b4b1 - // | | +-- Drop D(g_b_5, 50000003) - 50000003, - // | | - // | | +-- Make D(GaspB::drop_3, 30000004) - // | | | +-- Make D(g_b_5, 50000005) - // | | | | in g_B(b4b2) from GaspB::drop - // | | | +-- Drop D(g_b_5, 50000005) - 50000005, - // | | | - // | | +-- Drop D(GaspB::drop_3, 30000004) - 30000004, - // | | - // +-- Drop D(test_1, 10000000) - 10000000, - // | - // +-- Make D(GaspA::drop_2, 20000006) - // | | +-- Make D(f_a_4, 40000007) - // | | | in f_A(a3a0) from GaspA::drop - // | | +-- Drop D(f_a_4, 40000007) - 40000007, - // | | - // +-- Drop D(GaspA::drop_2, 20000006) - 20000006, - // | - // +-- Drop D(drop_6, 60000002) - 60000002 - // - ]); - - // For reference purposes, the old (incorrect) behavior would produce the following - // output, which you can compare to the above: - // - // created empty log - // +-- Make D(test_1, 10000000) - // | +-- Make D(g_b_5, 50000001) - // | | in g_B(b2b0) from E::drop, b=b4b0 - // | +-- Drop D(g_b_5, 50000001) - // | - // | +-- Make D(drop_6, 60000002) - // | | +-- Make D(g_b_5, 50000003) - // | | | in g_B(b2b0) from E::drop, b=b4b1 - // | | +-- Drop D(g_b_5, 50000003) - // | | - // | | +-- Make D(GaspB::drop_3, 30000004) - // | | | +-- Make D(g_b_5, 50000005) - // | | | | in g_B(b4b2) from GaspB::drop - // | | | +-- Drop D(g_b_5, 50000005) - // | | | - // | | +-- Drop D(GaspB::drop_3, 30000004) - // | | - // +-- Drop D(test_1, 10000000) - // | - // +-- Make D(GaspB::drop_3, 30000006) - // | | +-- Make D(f_a_4, 40000007) - // | | | in f_A(a3a0) from GaspB::drop - // | | +-- Drop D(f_a_4, 40000007) - // | | - // +-- Drop D(GaspB::drop_3, 30000006) - // | - // +-- Drop D(drop_6, 60000002) - - // Note that this calls f_A from GaspB::drop (and thus creates a D - // with a uid incorporating the origin of GaspB's drop that - // surrounds the f_A invocation), but the code as written only - // ever hands f_A off to instances of GaspA, and thus one should - // be able to prove the invariant that f_A is *only* invoked from - // from an instance of GaspA (either via the GaspA drop - // implementation or the E drop implementation). Yet the old (bad) - // behavior allowed a call to f_A to leak in while we are tearing - // down a value of type GaspB. -} - -fn test<'a>(log: d::Log<'a>) { - let _e = E::B(GaspB(g_b, 0xB4B0, log, D::new("test", 1, log)), true); -} - -struct GaspA<'a>(for <'b> fn(u32, &'b str, d::Log<'a>), u32, d::Log<'a>, d::D<'a>); -struct GaspB<'a>(for <'b> fn(u32, &'b str, d::Log<'a>), u32, d::Log<'a>, d::D<'a>); - -impl<'a> Drop for GaspA<'a> { - fn drop(&mut self) { - let _d = d::D::new("GaspA::drop", 2, self.2); - (self.0)(self.1, "GaspA::drop", self.2); - } -} - -impl<'a> Drop for GaspB<'a> { - fn drop(&mut self) { - let _d = d::D::new("GaspB::drop", 3, self.2); - (self.0)(self.1, "GaspB::drop", self.2); - } -} - -enum E<'a> { - A(GaspA<'a>, bool), B(GaspB<'a>, bool), -} - -fn f_a(x: u32, ctxt: &str, log: d::Log) { - let _d = d::D::new("f_a", 4, log); - d::println(&format!("in f_A({:x}) from {}", x, ctxt)); -} -fn g_b(y: u32, ctxt: &str, log: d::Log) { - let _d = d::D::new("g_b", 5, log); - d::println(&format!("in g_B({:x}) from {}", y, ctxt)); -} - -impl<'a> Drop for E<'a> { - fn drop(&mut self) { - let (do_drop, log) = match *self { - E::A(GaspA(ref f, ref mut val_a, log, ref _d_a), ref mut do_drop) => { - f(0xA1A0, &format!("E::drop, a={:x}", val_a), log); - *val_a += 1; - // swap in do_drop := false to avoid infinite dtor regress - (mem::replace(do_drop, false), log) - } - E::B(GaspB(ref g, ref mut val_b, log, ref _d_b), ref mut do_drop) => { - g(0xB2B0, &format!("E::drop, b={:x}", val_b), log); - *val_b += 1; - // swap in do_drop := false to avoid infinite dtor regress - (mem::replace(do_drop, false), log) - } - }; - - #[allow(unused_must_use)] - if do_drop { - mem::replace(self, E::A(GaspA(f_a, 0xA3A0, log, D::new("drop", 6, log)), true)); - } - } -} - -// This module provides simultaneous printouts of the dynamic extents -// of all of the D values, in addition to logging the order that each -// is dropped. -// -// This code is similar to a support code module embedded within -// test/run-pass/issue-123338-ensure-param-drop-order.rs; however, -// that (slightly simpler) code only identifies objects in the log via -// (creation) time-stamps; this incorporates both timestamping and the -// point of origin within the source code into the unique ID (uid). - -const PREF_INDENT: u32 = 20; - -pub mod d { - #![allow(unused_parens)] - use std::fmt; - use std::mem; - use std::cell::RefCell; - - static mut counter: u16 = 0; - static mut trails: u64 = 0; - - pub type Log<'a> = &'a RefCell<Vec<u32>>; - - pub fn current_width() -> u32 { - unsafe { max_width() - trails.leading_zeros() } - } - - pub fn max_width() -> u32 { - unsafe { - (mem::size_of_val(&trails)*8) as u32 - } - } - - pub fn indent_println(my_trails: u32, s: &str) { - let mut indent: String = String::new(); - for i in 0..my_trails { - unsafe { - if trails & (1 << i) != 0 { - indent = indent + "| "; - } else { - indent = indent + " "; - } - } - } - println!("{}{}", indent, s); - } - - pub fn println(s: &str) { - indent_println(super::PREF_INDENT, s); - } - - fn first_avail() -> u32 { - unsafe { - for i in 0..64 { - if trails & (1 << i) == 0 { - return i; - } - } - } - panic!("exhausted trails"); - } - - pub struct D<'a> { - name: &'static str, i: u8, uid: u32, trail: u32, log: Log<'a> - } - - impl<'a> fmt::Display for D<'a> { - fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { - write!(w, "D({}_{}, {})", self.name, self.i, self.uid) - } - } - - impl<'a> D<'a> { - pub fn new(name: &'static str, i: u8, log: Log<'a>) -> D<'a> { - unsafe { - let trail = first_avail(); - let ctr = ((i as u32) * 10_000_000) + (counter as u32); - counter += 1; - trails |= (1 << trail); - let ret = D { - name: name, i: i, log: log, uid: ctr, trail: trail - }; - indent_println(trail, &format!("+-- Make {}", ret)); - ret - } - } - } - - impl<'a> Drop for D<'a> { - fn drop(&mut self) { - unsafe { trails &= !(1 << self.trail); }; - self.log.borrow_mut().push(self.uid); - indent_println(self.trail, &format!("+-- Drop {}", self)); - indent_println(::PREF_INDENT, ""); - } - } -} |