about summary refs log tree commit diff
path: root/tests/ui/builtin-clone-unwind.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/builtin-clone-unwind.rs')
-rw-r--r--tests/ui/builtin-clone-unwind.rs61
1 files changed, 61 insertions, 0 deletions
diff --git a/tests/ui/builtin-clone-unwind.rs b/tests/ui/builtin-clone-unwind.rs
new file mode 100644
index 00000000000..16add6ff2f6
--- /dev/null
+++ b/tests/ui/builtin-clone-unwind.rs
@@ -0,0 +1,61 @@
+// run-pass
+// needs-unwind
+
+#![allow(unused_variables)]
+#![allow(unused_imports)]
+
+// Test that builtin implementations of `Clone` cleanup everything
+// in case of unwinding.
+
+use std::thread;
+use std::rc::Rc;
+
+struct S(Rc<()>);
+
+impl Clone for S {
+    fn clone(&self) -> Self {
+        if Rc::strong_count(&self.0) == 7 {
+            panic!("oops");
+        }
+
+        S(self.0.clone())
+    }
+}
+
+fn main() {
+    let counter = Rc::new(());
+
+    // Unwinding with tuples...
+    let ccounter = counter.clone();
+    let result = std::panic::catch_unwind(move || {
+        let _ = (
+            S(ccounter.clone()),
+            S(ccounter.clone()),
+            S(ccounter.clone()),
+            S(ccounter)
+        ).clone();
+    });
+
+    assert!(result.is_err());
+    assert_eq!(
+        1,
+        Rc::strong_count(&counter)
+    );
+
+    // ... and with arrays.
+    let ccounter = counter.clone();
+    let child = std::panic::catch_unwind(move || {
+        let _ = [
+            S(ccounter.clone()),
+            S(ccounter.clone()),
+            S(ccounter.clone()),
+            S(ccounter)
+        ].clone();
+    });
+
+    assert!(child.is_err());
+    assert_eq!(
+        1,
+        Rc::strong_count(&counter)
+    );
+}