about summary refs log tree commit diff
path: root/src/test
diff options
context:
space:
mode:
authorAriel Ben-Yehuda <ariel.byd@gmail.com>2016-05-17 02:26:18 +0300
committerAriel Ben-Yehuda <ariel.byd@gmail.com>2016-06-03 16:11:18 +0300
commita091cfd4f3be8677481a3a502bd96bdebd0de1bb (patch)
tree5c493419c53f456c04922247e550ad6c2741d4f9 /src/test
parentde7cb0fdd69c95158d217b9a913f1e25f3bfeef0 (diff)
downloadrust-a091cfd4f3be8677481a3a502bd96bdebd0de1bb.tar.gz
rust-a091cfd4f3be8677481a3a502bd96bdebd0de1bb.zip
implement drop elaboration
Fixes #30380
Diffstat (limited to 'src/test')
-rw-r--r--src/test/run-fail/issue-30380.rs44
-rw-r--r--src/test/run-pass/dynamic-drop.rs100
2 files changed, 144 insertions, 0 deletions
diff --git a/src/test/run-fail/issue-30380.rs b/src/test/run-fail/issue-30380.rs
new file mode 100644
index 00000000000..7bd9adcba9b
--- /dev/null
+++ b/src/test/run-fail/issue-30380.rs
@@ -0,0 +1,44 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// check that panics in destructors during assignment do not leave
+// destroyed values lying around for other destructors to observe.
+
+// error-pattern:panicking destructors ftw!
+
+struct Observer<'a>(&'a mut FilledOnDrop);
+
+struct FilledOnDrop(u32);
+impl Drop for FilledOnDrop {
+    fn drop(&mut self) {
+        if self.0 == 0 {
+            // this is only set during the destructor - safe
+            // code should not be able to observe this.
+            self.0 = 0x1c1c1c1c;
+            panic!("panicking destructors ftw!");
+        }
+    }
+}
+
+impl<'a> Drop for Observer<'a> {
+    fn drop(&mut self) {
+        assert_eq!(self.0 .0, 1);
+    }
+}
+
+fn foo(b: &mut Observer) {
+    *b.0 = FilledOnDrop(1);
+}
+
+fn main() {
+    let mut bomb = FilledOnDrop(0);
+    let mut observer = Observer(&mut bomb);
+    foo(&mut observer);
+}
diff --git a/src/test/run-pass/dynamic-drop.rs b/src/test/run-pass/dynamic-drop.rs
new file mode 100644
index 00000000000..48e7b7ca576
--- /dev/null
+++ b/src/test/run-pass/dynamic-drop.rs
@@ -0,0 +1,100 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::cell::RefCell;
+
+struct Allocator {
+    data: RefCell<Vec<bool>>,
+}
+
+impl Drop for Allocator {
+    fn drop(&mut self) {
+        let data = self.data.borrow();
+        if data.iter().any(|d| *d) {
+            panic!("missing free: {:?}", data);
+        }
+    }
+}
+
+impl Allocator {
+    fn new() -> Self { Allocator { data: RefCell::new(vec![]) } }
+    fn alloc(&self) -> Ptr {
+        let mut data = self.data.borrow_mut();
+        let addr = data.len();
+        data.push(true);
+        Ptr(addr, self)
+    }
+}
+
+struct Ptr<'a>(usize, &'a Allocator);
+impl<'a> Drop for Ptr<'a> {
+    fn drop(&mut self) {
+        match self.1.data.borrow_mut()[self.0] {
+            false => {
+                panic!("double free at index {:?}", self.0)
+            }
+            ref mut d => *d = false
+        }
+    }
+}
+
+fn dynamic_init(a: &Allocator, c: bool) {
+    let _x;
+    if c {
+        _x = Some(a.alloc());
+    }
+}
+
+fn dynamic_drop(a: &Allocator, c: bool) -> Option<Ptr> {
+    let x = a.alloc();
+    if c {
+        Some(x)
+    } else {
+        None
+    }
+}
+
+fn assignment2(a: &Allocator, c0: bool, c1: bool) {
+    let mut _v = a.alloc();
+    let mut _w = a.alloc();
+    if c0 {
+        drop(_v);
+    }
+    _v = _w;
+    if c1 {
+        _w = a.alloc();
+    }
+}
+
+fn assignment1(a: &Allocator, c0: bool) {
+    let mut _v = a.alloc();
+    let mut _w = a.alloc();
+    if c0 {
+        drop(_v);
+    }
+    _v = _w;
+}
+
+
+fn main() {
+    let a = Allocator::new();
+    dynamic_init(&a, false);
+    dynamic_init(&a, true);
+    dynamic_drop(&a, false);
+    dynamic_drop(&a, true);
+
+    assignment2(&a, false, false);
+    assignment2(&a, false, true);
+    assignment2(&a, true, false);
+    assignment2(&a, true, true);
+
+    assignment1(&a, false);
+    assignment1(&a, true);
+}