]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #54255 - spastorino:use-of-moved-value-error, r=nikomatsakis
authorbors <bors@rust-lang.org>
Thu, 20 Sep 2018 09:02:46 +0000 (09:02 +0000)
committerbors <bors@rust-lang.org>
Thu, 20 Sep 2018 09:02:46 +0000 (09:02 +0000)
Inspect parents paths when checking for moves

Closes #52669

src/librustc_mir/borrow_check/error_reporting.rs
src/librustc_mir/dataflow/move_paths/mod.rs
src/test/ui/nll/issue-52669.rs [new file with mode: 0644]
src/test/ui/nll/issue-52669.stderr [new file with mode: 0644]
src/test/ui/nll/move-subpaths-moves-root.rs [new file with mode: 0644]
src/test/ui/nll/move-subpaths-moves-root.stderr [new file with mode: 0644]

index fda6b34971625a63cca1c69e1538659c04c7da80..9187cb97e69e52f387e37605ae3df7a00b780aa1 100644 (file)
@@ -584,9 +584,20 @@ fn get_moved_indexes(&mut self, context: Context, mpi: MovePathIndex) -> Vec<Mov
                 // created by `StorageDead` and at the beginning
                 // of a function.
             } else {
+                // If we are found a use of a.b.c which was in error, then we want to look for
+                // moves not only of a.b.c but also a.b and a.
+                //
+                // Note that the moves data already includes "parent" paths, so we don't have to
+                // worry about the other case: that is, if there is a move of a.b.c, it is already
+                // marked as a move of a.b and a as well, so we will generate the correct errors
+                // there.
+                let mut mpis = vec![mpi];
+                let move_paths = &self.move_data.move_paths;
+                mpis.extend(move_paths[mpi].parents(move_paths));
+
                 for moi in &self.move_data.loc_map[l] {
                     debug!("report_use_of_moved_or_uninitialized: moi={:?}", moi);
-                    if self.move_data.moves[*moi].path == mpi {
+                    if mpis.contains(&self.move_data.moves[*moi].path) {
                         debug!("report_use_of_moved_or_uninitialized: found");
                         result.push(*moi);
 
index 7d7da6c96e8699fe3976836d544b743d783d6f77..58a2b9361032e579ac3767cf5ecab10ab11762ee 100644 (file)
@@ -97,6 +97,20 @@ pub struct MovePath<'tcx> {
     pub place: Place<'tcx>,
 }
 
+impl<'tcx> MovePath<'tcx> {
+    pub fn parents(&self, move_paths: &IndexVec<MovePathIndex, MovePath>) -> Vec<MovePathIndex> {
+        let mut parents = Vec::new();
+
+        let mut curr_parent = self.parent;
+        while let Some(parent_mpi) = curr_parent {
+            parents.push(parent_mpi);
+            curr_parent = move_paths[parent_mpi].parent;
+        }
+
+        parents
+    }
+}
+
 impl<'tcx> fmt::Debug for MovePath<'tcx> {
     fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
         write!(w, "MovePath {{")?;
diff --git a/src/test/ui/nll/issue-52669.rs b/src/test/ui/nll/issue-52669.rs
new file mode 100644 (file)
index 0000000..17a5999
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2018 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(nll)]
+
+struct A {
+    b: B,
+}
+
+#[derive(Clone)]
+struct B;
+
+fn foo(_: A) {}
+
+fn bar(mut a: A) -> B {
+    a.b = B;
+    foo(a);
+    a.b.clone()
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-52669.stderr b/src/test/ui/nll/issue-52669.stderr
new file mode 100644 (file)
index 0000000..ca1576f
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0382]: borrow of moved value: `a.b`
+  --> $DIR/issue-52669.rs:25:5
+   |
+LL |     foo(a);
+   |         - value moved here
+LL |     a.b.clone()
+   |     ^^^ value borrowed here after move
+   |
+   = note: move occurs because `a` has type `A`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/nll/move-subpaths-moves-root.rs b/src/test/ui/nll/move-subpaths-moves-root.rs
new file mode 100644 (file)
index 0000000..7a4e518
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2018 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(nll)]
+
+fn main() {
+    let x = (vec![1, 2, 3], );
+    drop(x.0);
+    drop(x);
+}
diff --git a/src/test/ui/nll/move-subpaths-moves-root.stderr b/src/test/ui/nll/move-subpaths-moves-root.stderr
new file mode 100644 (file)
index 0000000..76a1279
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/move-subpaths-moves-root.rs:16:10
+   |
+LL |     drop(x.0);
+   |          --- value moved here
+LL |     drop(x);
+   |          ^ value used here after move
+   |
+   = note: move occurs because `x.0` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.