about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFelix S. Klock II <pnkfelix@pnkfx.org>2015-04-03 20:09:04 +0200
committerFelix S. Klock II <pnkfelix@pnkfx.org>2015-04-04 09:24:29 +0200
commitc4216a50bd9662fd5e60946643c718ac0325d75f (patch)
tree395212d2dc77beb2bc6ad850f7ba9a6db8137130
parent05b8a106e45b0c8381c6bc89e76e7bb94b03a84c (diff)
downloadrust-c4216a50bd9662fd5e60946643c718ac0325d75f.tar.gz
rust-c4216a50bd9662fd5e60946643c718ac0325d75f.zip
Test cases for Issue 23338.
We ignore pretty for the params-outlive-temps-of-body test because the
way its comments are formatted exercises a known bug in the pretty
printer.
-rw-r--r--src/test/compile-fail/issue-23338-locals-die-before-temps-of-body.rs36
-rw-r--r--src/test/run-pass/issue-23338-ensure-param-drop-order.rs171
-rw-r--r--src/test/run-pass/issue-23338-params-outlive-temps-of-body.rs39
3 files changed, 246 insertions, 0 deletions
diff --git a/src/test/compile-fail/issue-23338-locals-die-before-temps-of-body.rs b/src/test/compile-fail/issue-23338-locals-die-before-temps-of-body.rs
new file mode 100644
index 00000000000..993893438e5
--- /dev/null
+++ b/src/test/compile-fail/issue-23338-locals-die-before-temps-of-body.rs
@@ -0,0 +1,36 @@
+// Copyright 2015 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.
+
+// This is just checking that we still reject code where temp values
+// are borrowing values for longer than they will be around.
+//
+// Compare to run-pass/issue-23338-params-outlive-temps-of-body.rs
+
+use std::cell::RefCell;
+
+fn foo(x: RefCell<String>) -> String {
+    let y = x;
+    y.borrow().clone() //~ ERROR `y` does not live long enough
+}
+
+fn foo2(x: RefCell<String>) -> String {
+    let ret = {
+        let y = x;
+        y.borrow().clone() //~ ERROR `y` does not live long enough
+    };
+    ret
+}
+
+fn main() {
+    let r = RefCell::new(format!("data"));
+    assert_eq!(foo(r), "data");
+    let r = RefCell::new(format!("data"));
+    assert_eq!(foo2(r), "data");
+}
diff --git a/src/test/run-pass/issue-23338-ensure-param-drop-order.rs b/src/test/run-pass/issue-23338-ensure-param-drop-order.rs
new file mode 100644
index 00000000000..0815ff084fb
--- /dev/null
+++ b/src/test/run-pass/issue-23338-ensure-param-drop-order.rs
@@ -0,0 +1,171 @@
+// Copyright 2015 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.
+
+// ignore-pretty : (#23623) problems when  ending with // comments
+
+// This test is ensuring that parameters are indeed dropped after
+// temporaries in a fn body.
+
+use std::cell::RefCell;
+
+use self::d::D;
+
+pub fn main() {
+    let log = RefCell::new(vec![]);
+    d::println(&format!("created empty log"));
+    test(&log);
+
+    assert_eq!(&log.borrow()[..],
+               [
+                   //                                    created empty log
+                   //    +-- Make D(da_0, 0)
+                   //    | +-- Make D(de_1, 1)
+                   //    | |                             calling foo
+                   //    | |                             entered foo
+                   //    | | +-- Make D(de_2, 2)
+                   //    | | | +-- Make D(da_1, 3)
+                   //    | | | | +-- Make D(de_3, 4)
+                   //    | | | | | +-- Make D(de_4, 5)
+                   3, // | | | +-- Drop D(da_1, 3)
+                   //    | | |   | |
+                   4, // | | |   +-- Drop D(de_3, 4)
+                   //    | | |     |
+                   //    | | |     |                     eval tail of foo
+                   //    | | | +-- Make D(de_5, 6)
+                   //    | | | | +-- Make D(de_6, 7)
+                   6, // | | | +-- Drop D(de_5, 6)
+                   //    | | |   | |
+                   5, // | | |   | +-- Drop D(de_4, 5)
+                   //    | | |   |
+                   2, // | | +-- Drop D(de_2, 2)
+                   //    | |     |
+                   1, // | +-- Drop D(de_1, 1)
+                   //    |       |
+                   0, // +-- Drop D(da_0, 0)
+                   //            |
+                   //            |                       result D(de_6, 7)
+                   7 //          +-- Drop D(de_6, 7)
+
+                       ]);
+}
+
+fn test<'a>(log: d::Log<'a>) {
+    let da = D::new("da", 0, log);
+    let de = D::new("de", 1, log);
+    d::println(&format!("calling foo"));
+    let result = foo(da, de);
+    d::println(&format!("result {}", result));
+}
+
+fn foo<'a>(da0: D<'a>, de1: D<'a>) -> D<'a> {
+    d::println(&format!("entered foo"));
+    let de2 = de1.incr();      // creates D(de_2, 2)
+    let de4 = {
+        let _da1 = da0.incr(); // creates D(da_1, 3)
+        de2.incr().incr()      // creates D(de_3, 4) and D(de_4, 5)
+    };
+    d::println(&format!("eval tail of foo"));
+    de4.incr().incr()          // creates D(de_5, 6) and D(de_6, 7)
+}
+
+// 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.
+
+const PREF_INDENT: u32 = 16;
+
+pub mod d {
+    #![allow(unused_parens)]
+    use std::fmt;
+    use std::mem;
+    use std::cell::RefCell;
+
+    static mut counter: u32 = 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: u32, 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: u32, log: Log<'a>) -> D<'a> {
+            unsafe {
+                let trail = first_avail();
+                let ctr = counter;
+                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
+            }
+        }
+        pub fn incr(&self) -> D<'a> {
+            D::new(self.name, self.i + 1, self.log)
+        }
+    }
+
+    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, "");
+        }
+    }
+}
diff --git a/src/test/run-pass/issue-23338-params-outlive-temps-of-body.rs b/src/test/run-pass/issue-23338-params-outlive-temps-of-body.rs
new file mode 100644
index 00000000000..cb9e852e526
--- /dev/null
+++ b/src/test/run-pass/issue-23338-params-outlive-temps-of-body.rs
@@ -0,0 +1,39 @@
+// Copyright 2015 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.
+
+// This is largely checking that we now accept code where temp values
+// are borrowing from the input parameters (the `foo` case below).
+//
+// Compare to run-pass/issue-23338-params-outlive-temps-of-body.rs
+//
+// (The `foo2` case is just for parity with the above test, which
+//  shows what happens when you move the `y`-binding to the inside of
+//  the inner block.)
+
+use std::cell::RefCell;
+
+fn foo(x: RefCell<String>) -> String {
+    x.borrow().clone()
+}
+
+fn foo2(x: RefCell<String>) -> String {
+    let y = x;
+    let ret = {
+        y.borrow().clone()
+    };
+    ret
+}
+
+pub fn main() {
+    let r = RefCell::new(format!("data"));
+    assert_eq!(foo(r), "data");
+    let r = RefCell::new(format!("data"));
+    assert_eq!(foo2(r), "data");
+}