]> git.lizzy.rs Git - rust.git/blobdiff - src/test/ui/drop/dynamic-drop.rs
Auto merge of #65140 - petrochenkov:disapp, r=nikomatsakis
[rust.git] / src / test / ui / drop / dynamic-drop.rs
index 6f9112ae006053a05edbe0f0bba31d4748d6b26d..8516bc3d96424cb452adb6ccd7051d11d21728b0 100644 (file)
@@ -17,7 +17,6 @@
 
 struct Allocator {
     data: RefCell<Vec<bool>>,
-    name: &'static str,
     failing_op: usize,
     cur_ops: Cell<usize>,
 }
@@ -29,18 +28,17 @@ impl Drop for Allocator {
     fn drop(&mut self) {
         let data = self.data.borrow();
         if data.iter().any(|d| *d) {
-            panic!("missing free in {:?}: {:?}", self.name, data);
+            panic!("missing free: {:?}", data);
         }
     }
 }
 
 impl Allocator {
-    fn new(failing_op: usize, name: &'static str) -> Self {
+    fn new(failing_op: usize) -> Self {
         Allocator {
             failing_op: failing_op,
             cur_ops: Cell::new(0),
-            data: RefCell::new(vec![]),
-            name,
+            data: RefCell::new(vec![])
         }
     }
     fn alloc(&self) -> Ptr<'_> {
@@ -55,6 +53,20 @@ fn alloc(&self) -> Ptr<'_> {
         data.push(true);
         Ptr(addr, self)
     }
+    // FIXME(#47949) Any use of this indicates a bug in rustc: we should never
+    // be leaking values in the cases here.
+    //
+    // Creates a `Ptr<'_>` and checks that the allocated value is leaked if the
+    // `failing_op` is in the list of exception.
+    fn alloc_leaked(&self, exceptions: Vec<usize>) -> Ptr<'_> {
+        let ptr = self.alloc();
+
+        if exceptions.iter().any(|operation| *operation == self.failing_op) {
+            let mut data = self.data.borrow_mut();
+            data[ptr.0] = false;
+        }
+        ptr
+    }
 }
 
 struct Ptr<'a>(usize, &'a Allocator);
@@ -62,7 +74,7 @@ impl<'a> Drop for Ptr<'a> {
     fn drop(&mut self) {
         match self.1.data.borrow_mut()[self.0] {
             false => {
-                panic!("double free in {:?} at index {:?}", self.1.name, self.0)
+                panic!("double free at index {:?}", self.0)
             }
             ref mut d => *d = false
         }
@@ -258,148 +270,79 @@ fn subslice_pattern_reassign(a: &Allocator) {
 }
 
 fn panic_after_return(a: &Allocator) -> Ptr<'_> {
+    // Panic in the drop of `p` or `q` can leak
+    let exceptions = vec![8, 9];
     a.alloc();
     let p = a.alloc();
     {
         a.alloc();
         let p = a.alloc();
-        a.alloc()
+        // FIXME (#47949) We leak values when we panic in a destructor after
+        // evaluating an expression with `rustc_mir::build::Builder::into`.
+        a.alloc_leaked(exceptions)
     }
 }
 
 fn panic_after_return_expr(a: &Allocator) -> Ptr<'_> {
+    // Panic in the drop of `p` or `q` can leak
+    let exceptions = vec![8, 9];
     a.alloc();
     let p = a.alloc();
     {
         a.alloc();
         let q = a.alloc();
-        return a.alloc();
+        // FIXME (#47949)
+        return a.alloc_leaked(exceptions);
     }
 }
 
 fn panic_after_init(a: &Allocator) {
+    // Panic in the drop of `r` can leak
+    let exceptions = vec![8];
     a.alloc();
     let p = a.alloc();
     let q = {
         a.alloc();
         let r = a.alloc();
-        a.alloc()
+        // FIXME (#47949)
+        a.alloc_leaked(exceptions)
     };
 }
 
 fn panic_after_init_temp(a: &Allocator) {
+    // Panic in the drop of `r` can leak
+    let exceptions = vec![8];
     a.alloc();
     let p = a.alloc();
     {
         a.alloc();
         let r = a.alloc();
-        a.alloc()
+        // FIXME (#47949)
+        a.alloc_leaked(exceptions)
     };
 }
 
 fn panic_after_init_by_loop(a: &Allocator) {
+    // Panic in the drop of `r` can leak
+    let exceptions = vec![8];
     a.alloc();
     let p = a.alloc();
     let q = loop {
         a.alloc();
         let r = a.alloc();
-        break a.alloc();
-    };
-}
-
-fn panic_after_init_by_match(a: &Allocator, b: bool) {
-    a.alloc();
-    let p = a.alloc();
-    loop {
-        let q = match b {
-            true => {
-                a.alloc();
-                let r = a.alloc();
-                a.alloc()
-            }
-            false => {
-                a.alloc();
-                let r = a.alloc();
-                break a.alloc();
-            }
-        };
-        return;
-    };
-}
-
-fn panic_after_init_by_match_with_guard(a: &Allocator, b: bool) {
-    a.alloc();
-    let p = a.alloc();
-    let q = match a.alloc() {
-        _ if b => {
-            a.alloc();
-            let r = a.alloc();
-            a.alloc()
-        }
-        _ => {
-            a.alloc();
-            let r = a.alloc();
-            a.alloc()
-        },
-    };
-}
-
-fn panic_after_init_by_match_with_bindings_and_guard(a: &Allocator, b: bool) {
-    a.alloc();
-    let p = a.alloc();
-    let q = match a.alloc() {
-        _x if b => {
-            a.alloc();
-            let r = a.alloc();
-            a.alloc()
-        }
-        _x => {
-            a.alloc();
-            let r = a.alloc();
-            a.alloc()
-        },
-    };
-}
-
-fn panic_after_init_by_match_with_ref_bindings_and_guard(a: &Allocator, b: bool) {
-    a.alloc();
-    let p = a.alloc();
-    let q = match a.alloc() {
-        ref _x if b => {
-            a.alloc();
-            let r = a.alloc();
-            a.alloc()
-        }
-        ref _x => {
-            a.alloc();
-            let r = a.alloc();
-            a.alloc()
-        },
-    };
-}
-
-fn panic_after_init_by_break_if(a: &Allocator, b: bool) {
-    a.alloc();
-    let p = a.alloc();
-    let q = loop {
-        let r = a.alloc();
-        break if b {
-            let s = a.alloc();
-            a.alloc()
-        } else {
-            a.alloc()
-        };
+        // FIXME (#47949)
+        break a.alloc_leaked(exceptions);
     };
 }
 
-fn run_test<F>(mut f: F, name: &'static str)
+fn run_test<F>(mut f: F)
     where F: FnMut(&Allocator)
 {
-    let first_alloc = Allocator::new(usize::MAX, name);
+    let first_alloc = Allocator::new(usize::MAX);
     f(&first_alloc);
 
     for failing_op in 1..first_alloc.cur_ops.get()+1 {
-        let alloc = Allocator::new(failing_op, name);
+        let alloc = Allocator::new(failing_op);
         let alloc = &alloc;
         let f = panic::AssertUnwindSafe(&mut f);
         let result = panic::catch_unwind(move || {
@@ -417,91 +360,77 @@ fn run_test<F>(mut f: F, name: &'static str)
     }
 }
 
-fn run_test_nopanic<F>(mut f: F, name: &'static str)
+fn run_test_nopanic<F>(mut f: F)
     where F: FnMut(&Allocator)
 {
-    let first_alloc = Allocator::new(usize::MAX, name);
+    let first_alloc = Allocator::new(usize::MAX);
     f(&first_alloc);
 }
 
-macro_rules! run_test {
-    ($e:expr) => { run_test($e, stringify!($e)); }
-}
-
 fn main() {
-    run_test!(|a| dynamic_init(a, false));
-    run_test!(|a| dynamic_init(a, true));
-    run_test!(|a| dynamic_drop(a, false));
-    run_test!(|a| dynamic_drop(a, true));
-
-    run_test!(|a| assignment2(a, false, false));
-    run_test!(|a| assignment2(a, false, true));
-    run_test!(|a| assignment2(a, true, false));
-    run_test!(|a| assignment2(a, true, true));
-
-    run_test!(|a| assignment1(a, false));
-    run_test!(|a| assignment1(a, true));
-
-    run_test!(|a| array_simple(a));
-    run_test!(|a| vec_simple(a));
-    run_test!(|a| vec_unreachable(a));
-
-    run_test!(|a| struct_dynamic_drop(a, false, false, false));
-    run_test!(|a| struct_dynamic_drop(a, false, false, true));
-    run_test!(|a| struct_dynamic_drop(a, false, true, false));
-    run_test!(|a| struct_dynamic_drop(a, false, true, true));
-    run_test!(|a| struct_dynamic_drop(a, true, false, false));
-    run_test!(|a| struct_dynamic_drop(a, true, false, true));
-    run_test!(|a| struct_dynamic_drop(a, true, true, false));
-    run_test!(|a| struct_dynamic_drop(a, true, true, true));
-
-    run_test!(|a| field_assignment(a, false));
-    run_test!(|a| field_assignment(a, true));
-
-    run_test!(|a| generator(a, 0));
-    run_test!(|a| generator(a, 1));
-    run_test!(|a| generator(a, 2));
-    run_test!(|a| generator(a, 3));
-
-    run_test!(|a| mixed_drop_and_nondrop(a));
-
-    run_test!(|a| slice_pattern_first(a));
-    run_test!(|a| slice_pattern_middle(a));
-    run_test!(|a| slice_pattern_two(a));
-    run_test!(|a| slice_pattern_last(a));
-    run_test!(|a| slice_pattern_one_of(a, 0));
-    run_test!(|a| slice_pattern_one_of(a, 1));
-    run_test!(|a| slice_pattern_one_of(a, 2));
-    run_test!(|a| slice_pattern_one_of(a, 3));
-
-    run_test!(|a| subslice_pattern_from_end(a, true));
-    run_test!(|a| subslice_pattern_from_end(a, false));
-    run_test!(|a| subslice_pattern_from_end_with_drop(a, true, true));
-    run_test!(|a| subslice_pattern_from_end_with_drop(a, true, false));
-    run_test!(|a| subslice_pattern_from_end_with_drop(a, false, true));
-    run_test!(|a| subslice_pattern_from_end_with_drop(a, false, false));
-    run_test!(|a| slice_pattern_reassign(a));
-    run_test!(|a| subslice_pattern_reassign(a));
-
-    run_test!(|a| {
+    run_test(|a| dynamic_init(a, false));
+    run_test(|a| dynamic_init(a, true));
+    run_test(|a| dynamic_drop(a, false));
+    run_test(|a| dynamic_drop(a, true));
+
+    run_test(|a| assignment2(a, false, false));
+    run_test(|a| assignment2(a, false, true));
+    run_test(|a| assignment2(a, true, false));
+    run_test(|a| assignment2(a, true, true));
+
+    run_test(|a| assignment1(a, false));
+    run_test(|a| assignment1(a, true));
+
+    run_test(|a| array_simple(a));
+    run_test(|a| vec_simple(a));
+    run_test(|a| vec_unreachable(a));
+
+    run_test(|a| struct_dynamic_drop(a, false, false, false));
+    run_test(|a| struct_dynamic_drop(a, false, false, true));
+    run_test(|a| struct_dynamic_drop(a, false, true, false));
+    run_test(|a| struct_dynamic_drop(a, false, true, true));
+    run_test(|a| struct_dynamic_drop(a, true, false, false));
+    run_test(|a| struct_dynamic_drop(a, true, false, true));
+    run_test(|a| struct_dynamic_drop(a, true, true, false));
+    run_test(|a| struct_dynamic_drop(a, true, true, true));
+
+    run_test(|a| field_assignment(a, false));
+    run_test(|a| field_assignment(a, true));
+
+    run_test(|a| generator(a, 0));
+    run_test(|a| generator(a, 1));
+    run_test(|a| generator(a, 2));
+    run_test(|a| generator(a, 3));
+
+    run_test(|a| mixed_drop_and_nondrop(a));
+
+    run_test(|a| slice_pattern_first(a));
+    run_test(|a| slice_pattern_middle(a));
+    run_test(|a| slice_pattern_two(a));
+    run_test(|a| slice_pattern_last(a));
+    run_test(|a| slice_pattern_one_of(a, 0));
+    run_test(|a| slice_pattern_one_of(a, 1));
+    run_test(|a| slice_pattern_one_of(a, 2));
+    run_test(|a| slice_pattern_one_of(a, 3));
+
+    run_test(|a| subslice_pattern_from_end(a, true));
+    run_test(|a| subslice_pattern_from_end(a, false));
+    run_test(|a| subslice_pattern_from_end_with_drop(a, true, true));
+    run_test(|a| subslice_pattern_from_end_with_drop(a, true, false));
+    run_test(|a| subslice_pattern_from_end_with_drop(a, false, true));
+    run_test(|a| subslice_pattern_from_end_with_drop(a, false, false));
+    run_test(|a| slice_pattern_reassign(a));
+    run_test(|a| subslice_pattern_reassign(a));
+
+    run_test(|a| {
         panic_after_return(a);
     });
-    run_test!(|a| {
+    run_test(|a| {
         panic_after_return_expr(a);
     });
-    run_test!(|a| panic_after_init(a));
-    run_test!(|a| panic_after_init_temp(a));
-    run_test!(|a| panic_after_init_by_loop(a));
-    run_test!(|a| panic_after_init_by_match(a, false));
-    run_test!(|a| panic_after_init_by_match(a, true));
-    run_test!(|a| panic_after_init_by_match_with_guard(a, false));
-    run_test!(|a| panic_after_init_by_match_with_guard(a, true));
-    run_test!(|a| panic_after_init_by_match_with_bindings_and_guard(a, false));
-    run_test!(|a| panic_after_init_by_match_with_bindings_and_guard(a, true));
-    run_test!(|a| panic_after_init_by_match_with_ref_bindings_and_guard(a, false));
-    run_test!(|a| panic_after_init_by_match_with_ref_bindings_and_guard(a, true));
-    run_test!(|a| panic_after_init_by_break_if(a, false));
-    run_test!(|a| panic_after_init_by_break_if(a, true));
-
-    run_test_nopanic(|a| union1(a), "|a| union1(a)");
+    run_test(|a| panic_after_init(a));
+    run_test(|a| panic_after_init_temp(a));
+    run_test(|a| panic_after_init_by_loop(a));
+
+    run_test_nopanic(|a| union1(a));
 }