From 1670a8cfb13fd384d9fd4ca47034cef99118c7a7 Mon Sep 17 00:00:00 2001
From: Niko Matsakis <niko@alum.mit.edu>
Date: Thu, 20 Jun 2013 15:11:47 -0400
Subject: [PATCH] Add new tests for irrefutable patterns used in various tricky
 ways

---
 .../borrowck-move-in-irrefut-pat.rs           | 16 ++++++++++++
 .../borrowck-move-out-of-struct-with-dtor.rs  | 22 ++++++++++++++++
 ...owck-move-out-of-tuple-struct-with-dtor.rs | 22 ++++++++++++++++
 .../compile-fail/regions-ref-in-fn-arg.rs     | 11 ++++++++
 .../run-pass/func-arg-incomplete-pattern.rs   | 20 ++++++++++++++
 src/test/run-pass/func-arg-ref-pattern.rs     | 24 +++++++++++++++++
 src/test/run-pass/func-arg-wild-pattern.rs    | 10 +++++++
 src/test/run-pass/let-destruct-ref.rs         |  5 ++++
 .../run-pass/match-drop-strs-issue-4541.rs    | 26 +++++++++++++++++++
 9 files changed, 156 insertions(+)
 create mode 100644 src/test/compile-fail/borrowck-move-in-irrefut-pat.rs
 create mode 100644 src/test/compile-fail/borrowck-move-out-of-struct-with-dtor.rs
 create mode 100644 src/test/compile-fail/borrowck-move-out-of-tuple-struct-with-dtor.rs
 create mode 100644 src/test/compile-fail/regions-ref-in-fn-arg.rs
 create mode 100644 src/test/run-pass/func-arg-incomplete-pattern.rs
 create mode 100644 src/test/run-pass/func-arg-ref-pattern.rs
 create mode 100644 src/test/run-pass/func-arg-wild-pattern.rs
 create mode 100644 src/test/run-pass/let-destruct-ref.rs
 create mode 100644 src/test/run-pass/match-drop-strs-issue-4541.rs

diff --git a/src/test/compile-fail/borrowck-move-in-irrefut-pat.rs b/src/test/compile-fail/borrowck-move-in-irrefut-pat.rs
new file mode 100644
index 00000000000..c99a1ee60d7
--- /dev/null
+++ b/src/test/compile-fail/borrowck-move-in-irrefut-pat.rs
@@ -0,0 +1,16 @@
+fn with(f: &fn(&~str)) {}
+
+fn arg_item(&_x: &~str) {}
+    //~^ ERROR cannot move out of dereference of & pointer
+
+fn arg_closure() {
+    with(|&_x| ())
+    //~^ ERROR cannot move out of dereference of & pointer
+}
+
+fn let_pat() {
+    let &_x = &~"hi";
+    //~^ ERROR cannot move out of dereference of & pointer
+}
+
+pub fn main() {}
\ No newline at end of file
diff --git a/src/test/compile-fail/borrowck-move-out-of-struct-with-dtor.rs b/src/test/compile-fail/borrowck-move-out-of-struct-with-dtor.rs
new file mode 100644
index 00000000000..827e35e0c83
--- /dev/null
+++ b/src/test/compile-fail/borrowck-move-out-of-struct-with-dtor.rs
@@ -0,0 +1,22 @@
+struct S {f:~str}
+impl Drop for S {
+    fn finalize(&self) { println(self.f); }
+}
+
+fn move_in_match() {
+    match S {f:~"foo"} {
+        S {f:_s} => {}
+        //~^ ERROR cannot move out of type `S`, which defines the `Drop` trait
+    }
+}
+
+fn move_in_let() {
+    let S {f:_s} = S {f:~"foo"};
+    //~^ ERROR cannot move out of type `S`, which defines the `Drop` trait
+}
+
+fn move_in_fn_arg(S {f:_s}: S) {
+    //~^ ERROR cannot move out of type `S`, which defines the `Drop` trait
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/borrowck-move-out-of-tuple-struct-with-dtor.rs b/src/test/compile-fail/borrowck-move-out-of-tuple-struct-with-dtor.rs
new file mode 100644
index 00000000000..6013999d835
--- /dev/null
+++ b/src/test/compile-fail/borrowck-move-out-of-tuple-struct-with-dtor.rs
@@ -0,0 +1,22 @@
+struct S(~str);
+impl Drop for S {
+    fn finalize(&self) { println(**self); }
+}
+
+fn move_in_match() {
+    match S(~"foo") {
+        S(_s) => {}
+        //~^ ERROR cannot move out of type `S`, which defines the `Drop` trait
+    }
+}
+
+fn move_in_let() {
+    let S(_s) = S(~"foo");
+    //~^ ERROR cannot move out of type `S`, which defines the `Drop` trait
+}
+
+fn move_in_fn_arg(S(_s): S) {
+    //~^ ERROR cannot move out of type `S`, which defines the `Drop` trait
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/regions-ref-in-fn-arg.rs b/src/test/compile-fail/regions-ref-in-fn-arg.rs
new file mode 100644
index 00000000000..f90fe924587
--- /dev/null
+++ b/src/test/compile-fail/regions-ref-in-fn-arg.rs
@@ -0,0 +1,11 @@
+fn arg_item(~ref x: ~int) -> &'static int {
+    x //~^ ERROR borrowed value does not live long enough
+}
+
+fn with<R>(f: &fn(~int) -> R) -> R { f(~3) }
+
+fn arg_closure() -> &'static int {
+    with(|~ref x| x) //~ ERROR borrowed value does not live long enough
+}
+
+fn main() {}
\ No newline at end of file
diff --git a/src/test/run-pass/func-arg-incomplete-pattern.rs b/src/test/run-pass/func-arg-incomplete-pattern.rs
new file mode 100644
index 00000000000..b08d3beae1b
--- /dev/null
+++ b/src/test/run-pass/func-arg-incomplete-pattern.rs
@@ -0,0 +1,20 @@
+// Test that we do not leak when the arg pattern must drop part of the
+// argument (in this case, the `y` field).
+
+struct Foo {
+    x: ~uint,
+    y: ~uint,
+}
+
+fn foo(Foo {x, _}: Foo) -> *uint {
+    let addr: *uint = &*x;
+    addr
+}
+
+fn main() {
+    let obj = ~1;
+    let objptr: *uint = &*obj;
+    let f = Foo {x: obj, y: ~2};
+    let xptr = foo(f);
+    assert_eq!(objptr, xptr);
+}
\ No newline at end of file
diff --git a/src/test/run-pass/func-arg-ref-pattern.rs b/src/test/run-pass/func-arg-ref-pattern.rs
new file mode 100644
index 00000000000..84c2b3acf35
--- /dev/null
+++ b/src/test/run-pass/func-arg-ref-pattern.rs
@@ -0,0 +1,24 @@
+// exec-env:RUST_POISON_ON_FREE=1
+
+// Test argument patterns where we create refs to the inside of `~`
+// boxes. Make sure that we don't free the box as we match the
+// pattern.
+
+fn getaddr(~ref x: ~uint) -> *uint {
+    let addr: *uint = &*x;
+    addr
+}
+
+fn checkval(~ref x: ~uint) -> uint {
+    *x
+}
+
+fn main() {
+    let obj = ~1;
+    let objptr: *uint = &*obj;
+    let xptr = getaddr(obj);
+    assert_eq!(objptr, xptr);
+
+    let obj = ~22;
+    assert_eq!(checkval(obj), 22);
+}
diff --git a/src/test/run-pass/func-arg-wild-pattern.rs b/src/test/run-pass/func-arg-wild-pattern.rs
new file mode 100644
index 00000000000..c2d60c85329
--- /dev/null
+++ b/src/test/run-pass/func-arg-wild-pattern.rs
@@ -0,0 +1,10 @@
+// Test that we can compile code that uses a `_` in function argument
+// patterns.
+
+fn foo((x, _): (int, int)) -> int {
+    x
+}
+
+fn main() {
+    assert_eq!(foo((22, 23)), 22);
+}
diff --git a/src/test/run-pass/let-destruct-ref.rs b/src/test/run-pass/let-destruct-ref.rs
new file mode 100644
index 00000000000..7f3f9110b1c
--- /dev/null
+++ b/src/test/run-pass/let-destruct-ref.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let x = ~"hello";
+    let ref y = x;
+    assert_eq!(x.slice(0, x.len()), y.slice(0, y.len()));
+}
diff --git a/src/test/run-pass/match-drop-strs-issue-4541.rs b/src/test/run-pass/match-drop-strs-issue-4541.rs
new file mode 100644
index 00000000000..ec65f36dc06
--- /dev/null
+++ b/src/test/run-pass/match-drop-strs-issue-4541.rs
@@ -0,0 +1,26 @@
+// Tests a tricky scenario involving string matching,
+// copying, and moving to ensure that we don't segfault
+// or double-free, as we were wont to do in the past.
+
+use std::io;
+
+fn parse_args() -> ~str {
+    let args = std::os::args();
+    let mut n = 0;
+
+    while n < args.len() {
+        match copy args[n] {
+            ~"-v" => (),
+            s => {
+                return s;
+            }
+        }
+        n += 1;
+    }
+
+    return ~""
+}
+
+fn main() {
+    io::println(parse_args());
+}