// 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);
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 {{")?;
--- /dev/null
+// 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() {}
--- /dev/null
+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`.
--- /dev/null
+// 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);
+}
--- /dev/null
+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`.