From e9029cec7b7acf4e94aaef051bb85aabee64394a Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sat, 15 Sep 2018 12:29:29 -0300 Subject: [PATCH] Inspect parents paths when checking for moves --- .../borrow_check/error_reporting.rs | 13 ++++++++- src/librustc_mir/dataflow/move_paths/mod.rs | 14 ++++++++++ src/test/ui/nll/issue-52669.rs | 28 +++++++++++++++++++ src/test/ui/nll/issue-52669.stderr | 13 +++++++++ src/test/ui/nll/move-subpaths-moves-root.rs | 17 +++++++++++ .../ui/nll/move-subpaths-moves-root.stderr | 13 +++++++++ 6 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/nll/issue-52669.rs create mode 100644 src/test/ui/nll/issue-52669.stderr create mode 100644 src/test/ui/nll/move-subpaths-moves-root.rs create mode 100644 src/test/ui/nll/move-subpaths-moves-root.stderr diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 4671332f2824c..b52a9c16ff7ea 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -564,9 +564,20 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // 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); diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index 7d7da6c96e869..58a2b9361032e 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -97,6 +97,20 @@ pub struct MovePath<'tcx> { pub place: Place<'tcx>, } +impl<'tcx> MovePath<'tcx> { + pub fn parents(&self, move_paths: &IndexVec) -> Vec { + 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 index 0000000000000..17a59997e91ea --- /dev/null +++ b/src/test/ui/nll/issue-52669.rs @@ -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 or the MIT license +// , 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 index 0000000000000..ca1576fad7a86 --- /dev/null +++ b/src/test/ui/nll/issue-52669.stderr @@ -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 index 0000000000000..7a4e518f97778 --- /dev/null +++ b/src/test/ui/nll/move-subpaths-moves-root.rs @@ -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 or the MIT license +// , 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 index 0000000000000..76a1279750ff3 --- /dev/null +++ b/src/test/ui/nll/move-subpaths-moves-root.stderr @@ -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`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`.