about summary refs log tree commit diff
path: root/src/test
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-11-25 15:48:05 +0000
committerbors <bors@rust-lang.org>2014-11-25 15:48:05 +0000
commit0e06f71747749e33ca590c334658bddde97a7e54 (patch)
tree57a3fc9cca2562ea6595e95c54233915ce5b4c95 /src/test
parent48ca6d1840818e4a8977d00ed62cf0e8e0e5d193 (diff)
parent5fbe0cac7c568774082755ecc098caba98352a1e (diff)
downloadrust-0e06f71747749e33ca590c334658bddde97a7e54.tar.gz
rust-0e06f71747749e33ca590c334658bddde97a7e54.zip
auto merge of #18234 : pnkfelix/rust/fsk-type-fragments-for-needsdrop-2, r=nikomatsakis
Code to fragment paths into pieces based on subparts being moved around, e.g. moving `x.1` out of a tuple `(A,B,C)` leaves behind the fragments `x.0: A` and `x.2: C`.  Further discussion in borrowck/doc.rs.

Includes differentiation between assigned_fragments and moved_fragments, support for all-but-one array fragments, and instrumentation to print out the moved/assigned/unmmoved/parents for each function, factored out into a separate submodule.

These fragments can then be used by `trans` to inject stack-local dynamic drop flags.  (They also can be hooked up with dataflow to reduce the expected number of injected flags.)
Diffstat (limited to 'src/test')
-rw-r--r--src/test/compile-fail/move-fragments-1.rs58
-rw-r--r--src/test/compile-fail/move-fragments-2.rs85
-rw-r--r--src/test/compile-fail/move-fragments-3.rs47
-rw-r--r--src/test/compile-fail/move-fragments-4.rs39
-rw-r--r--src/test/compile-fail/move-fragments-5.rs92
-rw-r--r--src/test/compile-fail/move-fragments-6.rs59
-rw-r--r--src/test/compile-fail/move-fragments-7.rs46
-rw-r--r--src/test/compile-fail/move-fragments-8.rs39
-rw-r--r--src/test/compile-fail/move-fragments-9.rs100
9 files changed, 565 insertions, 0 deletions
diff --git a/src/test/compile-fail/move-fragments-1.rs b/src/test/compile-fail/move-fragments-1.rs
new file mode 100644
index 00000000000..ccf12cf79e1
--- /dev/null
+++ b/src/test/compile-fail/move-fragments-1.rs
@@ -0,0 +1,58 @@
+// Copyright 2014 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.
+
+#![feature(tuple_indexing)]
+
+// Test that we correctly compute the move fragments for a fn.
+//
+// Note that the code below is not actually incorrect; the
+// `rustc_move_fragments` attribute is a hack that uses the error
+// reporting mechanisms as a channel for communicating from the
+// internals of the compiler.
+
+// These are all fairly trivial cases: unused variables or direct
+// drops of substructure.
+
+pub struct D { d: int }
+impl Drop for D { fn drop(&mut self) { } }
+
+#[rustc_move_fragments]
+pub fn test_noop() {
+}
+
+#[rustc_move_fragments]
+pub fn test_take(_x: D) {
+    //~^ ERROR                  assigned_leaf_path: `$(local _x)`
+}
+
+pub struct Pair<X,Y> { x: X, y: Y }
+
+#[rustc_move_fragments]
+pub fn test_take_struct(_p: Pair<D, D>) {
+    //~^ ERROR                  assigned_leaf_path: `$(local _p)`
+}
+
+#[rustc_move_fragments]
+pub fn test_drop_struct_part(p: Pair<D, D>) {
+    //~^ ERROR                 parent_of_fragments: `$(local p)`
+    //~| ERROR                     moved_leaf_path: `$(local p).x`
+    //~| ERROR                    unmoved_fragment: `$(local p).y`
+    drop(p.x);
+}
+
+#[rustc_move_fragments]
+pub fn test_drop_tuple_part(p: (D, D)) {
+    //~^ ERROR                 parent_of_fragments: `$(local p)`
+    //~| ERROR                     moved_leaf_path: `$(local p).#0`
+    //~| ERROR                    unmoved_fragment: `$(local p).#1`
+    drop(p.0);
+}
+
+pub fn main() { }
diff --git a/src/test/compile-fail/move-fragments-2.rs b/src/test/compile-fail/move-fragments-2.rs
new file mode 100644
index 00000000000..ceb1d5a0f09
--- /dev/null
+++ b/src/test/compile-fail/move-fragments-2.rs
@@ -0,0 +1,85 @@
+// Copyright 2014 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.
+
+// Test that we correctly compute the move fragments for a fn.
+//
+// Note that the code below is not actually incorrect; the
+// `rustc_move_fragments` attribute is a hack that uses the error
+// reporting mechanisms as a channel for communicating from the
+// internals of the compiler.
+
+// These are checking that enums are tracked; note that their output
+// paths include "downcasts" of the path to a particular enum.
+
+use self::Lonely::{Zero, One, Two};
+
+pub struct D { d: int }
+impl Drop for D { fn drop(&mut self) { } }
+
+pub enum Lonely<X,Y> { Zero, One(X), Two(X, Y) }
+
+#[rustc_move_fragments]
+pub fn test_match_partial(p: Lonely<D, D>) {
+    //~^ ERROR                 parent_of_fragments: `$(local p)`
+    //~| ERROR                  assigned_leaf_path: `($(local p) as Zero)`
+    match p {
+        Zero(..) => {}
+        _ => {}
+    }
+}
+
+#[rustc_move_fragments]
+pub fn test_match_full(p: Lonely<D, D>) {
+    //~^ ERROR                 parent_of_fragments: `$(local p)`
+    //~| ERROR                  assigned_leaf_path: `($(local p) as Zero)`
+    //~| ERROR                  assigned_leaf_path: `($(local p) as One)`
+    //~| ERROR                  assigned_leaf_path: `($(local p) as Two)`
+    match p {
+        Zero(..) => {}
+        One(..) => {}
+        Two(..) => {}
+    }
+}
+
+#[rustc_move_fragments]
+pub fn test_match_bind_one(p: Lonely<D, D>) {
+    //~^ ERROR                 parent_of_fragments: `$(local p)`
+    //~| ERROR                  assigned_leaf_path: `($(local p) as Zero)`
+    //~| ERROR                 parent_of_fragments: `($(local p) as One)`
+    //~| ERROR                     moved_leaf_path: `($(local p) as One).#0`
+    //~| ERROR                  assigned_leaf_path: `($(local p) as Two)`
+    //~| ERROR                  assigned_leaf_path: `$(local data)`
+    match p {
+        Zero(..) => {}
+        One(data) => {}
+        Two(..) => {}
+    }
+}
+
+#[rustc_move_fragments]
+pub fn test_match_bind_many(p: Lonely<D, D>) {
+    //~^ ERROR                 parent_of_fragments: `$(local p)`
+    //~| ERROR                  assigned_leaf_path: `($(local p) as Zero)`
+    //~| ERROR                 parent_of_fragments: `($(local p) as One)`
+    //~| ERROR                     moved_leaf_path: `($(local p) as One).#0`
+    //~| ERROR                  assigned_leaf_path: `$(local data)`
+    //~| ERROR                 parent_of_fragments: `($(local p) as Two)`
+    //~| ERROR                     moved_leaf_path: `($(local p) as Two).#0`
+    //~| ERROR                     moved_leaf_path: `($(local p) as Two).#1`
+    //~| ERROR                  assigned_leaf_path: `$(local left)`
+    //~| ERROR                  assigned_leaf_path: `$(local right)`
+    match p {
+        Zero(..) => {}
+        One(data) => {}
+        Two(left, right) => {}
+    }
+}
+
+pub fn main() { }
diff --git a/src/test/compile-fail/move-fragments-3.rs b/src/test/compile-fail/move-fragments-3.rs
new file mode 100644
index 00000000000..4540b0c5a91
--- /dev/null
+++ b/src/test/compile-fail/move-fragments-3.rs
@@ -0,0 +1,47 @@
+// Copyright 2014 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.
+
+// Test that we correctly compute the move fragments for a fn.
+//
+// Note that the code below is not actually incorrect; the
+// `rustc_move_fragments` attribute is a hack that uses the error
+// reporting mechanisms as a channel for communicating from the
+// internals of the compiler.
+
+// This checks the handling of `_` within variants, especially when mixed
+// with bindings.
+
+use self::Lonely::{Zero, One, Two};
+
+pub struct D { d: int }
+impl Drop for D { fn drop(&mut self) { } }
+
+pub enum Lonely<X,Y> { Zero, One(X), Two(X, Y) }
+
+#[rustc_move_fragments]
+pub fn test_match_bind_and_underscore(p: Lonely<D, D>) {
+    //~^ ERROR                 parent_of_fragments: `$(local p)`
+    //~| ERROR                  assigned_leaf_path: `($(local p) as Zero)`
+    //~| ERROR                  assigned_leaf_path: `($(local p) as One)`
+    //~| ERROR                 parent_of_fragments: `($(local p) as Two)`
+    //~| ERROR                     moved_leaf_path: `($(local p) as Two).#0`
+    //~| ERROR                    unmoved_fragment: `($(local p) as Two).#1`
+    //~| ERROR                  assigned_leaf_path: `$(local left)`
+
+    match p {
+        Zero(..) => {}
+
+        One(_) => {}       // <-- does not fragment `($(local p) as One)` ...
+
+        Two(left, _) => {} // <-- ... *does* fragment `($(local p) as Two)`.
+    }
+}
+
+pub fn main() { }
diff --git a/src/test/compile-fail/move-fragments-4.rs b/src/test/compile-fail/move-fragments-4.rs
new file mode 100644
index 00000000000..dc43dcb9b0e
--- /dev/null
+++ b/src/test/compile-fail/move-fragments-4.rs
@@ -0,0 +1,39 @@
+// Copyright 2014 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.
+
+// Test that we correctly compute the move fragments for a fn.
+//
+// Note that the code below is not actually incorrect; the
+// `rustc_move_fragments` attribute is a hack that uses the error
+// reporting mechanisms as a channel for communicating from the
+// internals of the compiler.
+
+// This checks that a move of deep structure is properly tracked. (An
+// early draft of the code did not properly traverse up through all of
+// the parents of the leaf fragment.)
+
+pub struct D { d: int }
+impl Drop for D { fn drop(&mut self) { } }
+
+pub struct Pair<X,Y> { x: X, y: Y }
+
+#[rustc_move_fragments]
+pub fn test_move_substructure(pppp: Pair<Pair<Pair<Pair<D,D>, D>, D>, D>) {
+    //~^ ERROR                 parent_of_fragments: `$(local pppp)`
+    //~| ERROR                 parent_of_fragments: `$(local pppp).x`
+    //~| ERROR                 parent_of_fragments: `$(local pppp).x.x`
+    //~| ERROR                    unmoved_fragment: `$(local pppp).x.x.x`
+    //~| ERROR                     moved_leaf_path: `$(local pppp).x.x.y`
+    //~| ERROR                    unmoved_fragment: `$(local pppp).x.y`
+    //~| ERROR                    unmoved_fragment: `$(local pppp).y`
+    drop(pppp.x.x.y);
+}
+
+pub fn main() { }
diff --git a/src/test/compile-fail/move-fragments-5.rs b/src/test/compile-fail/move-fragments-5.rs
new file mode 100644
index 00000000000..df069461ab7
--- /dev/null
+++ b/src/test/compile-fail/move-fragments-5.rs
@@ -0,0 +1,92 @@
+// Copyright 2014 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.
+
+// Test that we correctly compute the move fragments for a fn.
+//
+// Note that the code below is not actually incorrect; the
+// `rustc_move_fragments` attribute is a hack that uses the error
+// reporting mechanisms as a channel for communicating from the
+// internals of the compiler.
+
+// This is the first test that checks moving into local variables.
+
+pub struct D { d: int }
+impl Drop for D { fn drop(&mut self) { } }
+
+pub struct Pair<X,Y> { x: X, y: Y }
+
+#[rustc_move_fragments]
+pub fn test_move_field_to_local(p: Pair<D, D>) {
+    //~^ ERROR                 parent_of_fragments: `$(local p)`
+    //~| ERROR                     moved_leaf_path: `$(local p).x`
+    //~| ERROR                    unmoved_fragment: `$(local p).y`
+    //~| ERROR                  assigned_leaf_path: `$(local _x)`
+    let _x = p.x;
+}
+
+#[rustc_move_fragments]
+pub fn test_move_field_to_local_to_local(p: Pair<D, D>) {
+    //~^ ERROR                 parent_of_fragments: `$(local p)`
+    //~| ERROR                     moved_leaf_path: `$(local p).x`
+    //~| ERROR                    unmoved_fragment: `$(local p).y`
+    //~| ERROR                  assigned_leaf_path: `$(local _x)`
+    //~| ERROR                     moved_leaf_path: `$(local _x)`
+    //~| ERROR                  assigned_leaf_path: `$(local _y)`
+    let _x = p.x;
+    let _y = _x;
+}
+
+// In the following fn's `test_move_field_to_local_delayed` and
+// `test_uninitialized_local` , the instrumentation reports that `_x`
+// is moved. This is unlike `test_move_field_to_local`, where `_x` is
+// just reported as an assigned_leaf_path. Presumably because this is
+// how we represent that it did not have an initalizing expression at
+// the binding site.
+
+#[rustc_move_fragments]
+pub fn test_uninitialized_local(_p: Pair<D, D>) {
+    //~^ ERROR                  assigned_leaf_path: `$(local _p)`
+    //~| ERROR                     moved_leaf_path: `$(local _x)`
+    let _x: D;
+}
+
+#[rustc_move_fragments]
+pub fn test_move_field_to_local_delayed(p: Pair<D, D>) {
+    //~^ ERROR                 parent_of_fragments: `$(local p)`
+    //~| ERROR                     moved_leaf_path: `$(local p).x`
+    //~| ERROR                    unmoved_fragment: `$(local p).y`
+    //~| ERROR                  assigned_leaf_path: `$(local _x)`
+    //~| ERROR                     moved_leaf_path: `$(local _x)`
+    let _x;
+    _x = p.x;
+}
+
+#[rustc_move_fragments]
+pub fn test_move_field_mut_to_local(mut p: Pair<D, D>) {
+    //~^ ERROR                 parent_of_fragments: `$(local mut p)`
+    //~| ERROR                     moved_leaf_path: `$(local mut p).x`
+    //~| ERROR                    unmoved_fragment: `$(local mut p).y`
+    //~| ERROR                  assigned_leaf_path: `$(local _x)`
+    let _x = p.x;
+}
+
+#[rustc_move_fragments]
+pub fn test_move_field_to_local_to_local_mut(p: Pair<D, D>) {
+    //~^ ERROR                 parent_of_fragments: `$(local p)`
+    //~| ERROR                     moved_leaf_path: `$(local p).x`
+    //~| ERROR                    unmoved_fragment: `$(local p).y`
+    //~| ERROR                  assigned_leaf_path: `$(local mut _x)`
+    //~| ERROR                     moved_leaf_path: `$(local mut _x)`
+    //~| ERROR                  assigned_leaf_path: `$(local _y)`
+    let mut _x = p.x;
+    let _y = _x;
+}
+
+pub fn main() {}
diff --git a/src/test/compile-fail/move-fragments-6.rs b/src/test/compile-fail/move-fragments-6.rs
new file mode 100644
index 00000000000..b249d0d7397
--- /dev/null
+++ b/src/test/compile-fail/move-fragments-6.rs
@@ -0,0 +1,59 @@
+// Copyright 2014 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.
+
+// Test that we correctly compute the move fragments for a fn.
+//
+// Note that the code below is not actually incorrect; the
+// `rustc_move_fragments` attribute is a hack that uses the error
+// reporting mechanisms as a channel for communicating from the
+// internals of the compiler.
+
+// Test that moving into a field (i.e. overwriting it) fragments the
+// receiver.
+
+use std::mem::drop;
+
+pub struct Pair<X,Y> { x: X, y: Y }
+
+#[rustc_move_fragments]
+pub fn test_overwrite_uninit_field<Z>(z: Z) {
+    //~^ ERROR                 parent_of_fragments: `$(local mut p)`
+    //~| ERROR                  assigned_leaf_path: `$(local z)`
+    //~| ERROR                     moved_leaf_path: `$(local z)`
+    //~| ERROR                  assigned_leaf_path: `$(local mut p).x`
+    //~| ERROR                    unmoved_fragment: `$(local mut p).y`
+
+    let mut p: Pair<Z,Z>;
+    p.x = z;
+}
+
+#[rustc_move_fragments]
+pub fn test_overwrite_moved_field<Z>(mut p: Pair<Z,Z>, z: Z) {
+    //~^ ERROR                 parent_of_fragments: `$(local mut p)`
+    //~| ERROR                  assigned_leaf_path: `$(local z)`
+    //~| ERROR                     moved_leaf_path: `$(local z)`
+    //~| ERROR                  assigned_leaf_path: `$(local mut p).y`
+    //~| ERROR                    unmoved_fragment: `$(local mut p).x`
+
+    drop(p);
+    p.y = z;
+}
+
+#[rustc_move_fragments]
+pub fn test_overwrite_same_field<Z>(mut p: Pair<Z,Z>) {
+    //~^ ERROR                 parent_of_fragments: `$(local mut p)`
+    //~| ERROR                     moved_leaf_path: `$(local mut p).x`
+    //~| ERROR                  assigned_leaf_path: `$(local mut p).x`
+    //~| ERROR                    unmoved_fragment: `$(local mut p).y`
+
+    p.x = p.x;
+}
+
+pub fn main() { }
diff --git a/src/test/compile-fail/move-fragments-7.rs b/src/test/compile-fail/move-fragments-7.rs
new file mode 100644
index 00000000000..6b2c77bcac1
--- /dev/null
+++ b/src/test/compile-fail/move-fragments-7.rs
@@ -0,0 +1,46 @@
+// Copyright 2014 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.
+
+// Test that we correctly compute the move fragments for a fn.
+//
+// Note that the code below is not actually incorrect; the
+// `rustc_move_fragments` attribute is a hack that uses the error
+// reporting mechanisms as a channel for communicating from the
+// internals of the compiler.
+
+// Test that moving a Box<T> fragments its containing structure, for
+// both moving out of the structure (i.e. reading `*p.x`) and writing
+// into the container (i.e. writing `*p.x`).
+
+pub struct D { d: int }
+impl Drop for D { fn drop(&mut self) { } }
+
+pub struct Pair<X,Y> { x: X, y: Y }
+
+#[rustc_move_fragments]
+pub fn test_deref_box_field(p: Pair<Box<D>, Box<D>>) {
+    //~^ ERROR                 parent_of_fragments: `$(local p)`
+    //~| ERROR                 parent_of_fragments: `$(local p).x`
+    //~| ERROR                     moved_leaf_path: `$(local p).x.*`
+    //~| ERROR                    unmoved_fragment: `$(local p).y`
+    //~| ERROR                  assigned_leaf_path: `$(local i)`
+    let i : D = *p.x;
+}
+
+#[rustc_move_fragments]
+pub fn test_overwrite_deref_box_field(mut p: Pair<Box<D>, Box<D>>) {
+    //~^ ERROR                 parent_of_fragments: `$(local mut p)`
+    //~| ERROR                 parent_of_fragments: `$(local mut p).x`
+    //~| ERROR                  assigned_leaf_path: `$(local mut p).x.*`
+    //~| ERROR                    unmoved_fragment: `$(local mut p).y`
+    *p.x = D { d: 3 };
+}
+
+pub fn main() { }
diff --git a/src/test/compile-fail/move-fragments-8.rs b/src/test/compile-fail/move-fragments-8.rs
new file mode 100644
index 00000000000..40ab541128c
--- /dev/null
+++ b/src/test/compile-fail/move-fragments-8.rs
@@ -0,0 +1,39 @@
+// Copyright 2014 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.
+
+// Test that we correctly compute the move fragments for a fn.
+//
+// Note that the code below is not actually incorrect; the
+// `rustc_move_fragments` attribute is a hack that uses the error
+// reporting mechanisms as a channel for communicating from the
+// internals of the compiler.
+
+// Test that assigning into a `&T` within structured container does
+// *not* fragment its containing structure.
+//
+// Compare against the `Box<T>` handling in move-fragments-7.rs. Note
+// also that in this case we cannot do a move out of `&T`, so we only
+// test writing `*p.x` here.
+
+pub struct D { d: int }
+impl Drop for D { fn drop(&mut self) { } }
+
+pub struct Pair<X,Y> { x: X, y: Y }
+
+#[rustc_move_fragments]
+pub fn test_overwrite_deref_ampersand_field<'a>(p: Pair<&'a mut D, &'a D>) {
+    //~^ ERROR                 parent_of_fragments: `$(local p)`
+    //~| ERROR                 parent_of_fragments: `$(local p).x`
+    //~| ERROR                  assigned_leaf_path: `$(local p).x.*`
+    //~| ERROR                    unmoved_fragment: `$(local p).y`
+    *p.x = D { d: 3 };
+}
+
+pub fn main() { }
diff --git a/src/test/compile-fail/move-fragments-9.rs b/src/test/compile-fail/move-fragments-9.rs
new file mode 100644
index 00000000000..ce05087f659
--- /dev/null
+++ b/src/test/compile-fail/move-fragments-9.rs
@@ -0,0 +1,100 @@
+// Copyright 2014 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.
+
+// Test moving array structures, e.g. `[T, ..3]` as well as moving
+// elements in and out of such arrays.
+//
+// Note also that the `test_move_array_then_overwrite` tests represent
+// cases that we probably should make illegal.
+
+pub struct D { d: int }
+impl Drop for D { fn drop(&mut self) { } }
+
+#[rustc_move_fragments]
+pub fn test_move_array_via_return(a: [D, ..3]) -> [D, ..3] {
+    //~^ ERROR                  assigned_leaf_path: `$(local a)`
+    //~| ERROR                     moved_leaf_path: `$(local a)`
+    return a;
+}
+
+#[rustc_move_fragments]
+pub fn test_move_array_into_recv(a: [D, ..3], recv: &mut [D, ..3]) {
+    //~^ ERROR                 parent_of_fragments: `$(local recv)`
+    //~| ERROR                  assigned_leaf_path: `$(local a)`
+    //~| ERROR                     moved_leaf_path: `$(local a)`
+    //~| ERROR                  assigned_leaf_path: `$(local recv).*`
+    *recv = a;
+}
+
+#[rustc_move_fragments]
+pub fn test_extract_array_elem(a: [D, ..3], i: uint) -> D {
+    //~^ ERROR                 parent_of_fragments: `$(local a)`
+    //~| ERROR                  assigned_leaf_path: `$(local i)`
+    //~| ERROR                     moved_leaf_path: `$(local a).[]`
+    //~| ERROR                    unmoved_fragment: `$(allbutone $(local a).[])`
+    a[i]
+}
+
+#[rustc_move_fragments]
+pub fn test_overwrite_array_elem(mut a: [D, ..3], i: uint, d: D) {
+    //~^ ERROR                 parent_of_fragments: `$(local mut a)`
+    //~| ERROR                  assigned_leaf_path: `$(local i)`
+    //~| ERROR                  assigned_leaf_path: `$(local d)`
+    //~| ERROR                     moved_leaf_path: `$(local d)`
+    //~| ERROR                  assigned_leaf_path: `$(local mut a).[]`
+    //~| ERROR                    unmoved_fragment: `$(allbutone $(local mut a).[])`
+    a[i] = d;
+}
+
+// FIXME (pnkfelix): Both test_move_array_then_overwrite_elem1 and
+// test_move_array_then_overwrite_elem2 illustrate a behavior that
+// we need to make illegal if we want to get rid of drop-flags.
+// See RFC PR 320 for more discussion.
+
+#[rustc_move_fragments]
+pub fn test_move_array_then_overwrite_elem1(mut a: [D, ..3], i: uint, recv: &mut [D, ..3], d: D) {
+    //~^ ERROR                 parent_of_fragments: `$(local mut a)`
+    //~| ERROR                 parent_of_fragments: `$(local recv)`
+    //~| ERROR                  assigned_leaf_path: `$(local recv).*`
+    //~| ERROR                  assigned_leaf_path: `$(local i)`
+    //~| ERROR                  assigned_leaf_path: `$(local d)`
+    //~| ERROR                     moved_leaf_path: `$(local d)`
+    //~| ERROR                  assigned_leaf_path: `$(local mut a).[]`
+    //~| ERROR                    unmoved_fragment: `$(allbutone $(local mut a).[])`
+
+    // This test covers the case where the array contents have been all moved away, but
+    // we still need to deal with new initializing writes into the array.
+    *recv = a;
+    a[i] = d;
+}
+
+#[rustc_move_fragments]
+pub fn test_move_array_then_overwrite_elem2(mut a: [D, ..3], i: uint, j: uint,
+                                            recv: &mut [D, ..3], d1: D, d2: D) {
+    //~^^ ERROR                parent_of_fragments: `$(local mut a)`
+    //~| ERROR                 parent_of_fragments: `$(local recv)`
+    //~| ERROR                  assigned_leaf_path: `$(local recv).*`
+    //~| ERROR                  assigned_leaf_path: `$(local i)`
+    //~| ERROR                  assigned_leaf_path: `$(local j)`
+    //~| ERROR                  assigned_leaf_path: `$(local d1)`
+    //~| ERROR                  assigned_leaf_path: `$(local d2)`
+    //~| ERROR                     moved_leaf_path: `$(local d1)`
+    //~| ERROR                     moved_leaf_path: `$(local d2)`
+    //~| ERROR                  assigned_leaf_path: `$(local mut a).[]`
+    //~| ERROR                    unmoved_fragment: `$(allbutone $(local mut a).[])`
+
+    // This test covers the case where the array contents have been all moved away, but
+    // we still need to deal with new initializing writes into the array.
+    *recv = a;
+    a[i] = d1;
+    a[j] = d2;
+}
+
+pub fn main() { }