diff options
| author | David Wood <david@davidtw.co> | 2017-11-14 19:47:31 +0000 |
|---|---|---|
| committer | David Wood <david@davidtw.co> | 2017-11-16 23:37:28 +0000 |
| commit | 7db49b9612e97e29bbd933b550f156d2ea4de3e6 (patch) | |
| tree | def71efd193b11d3b26439ce0f7b435e11c7b558 /src | |
| parent | d0f8e2913a93573c78cddfd297944cff4eb4c41a (diff) | |
| download | rust-7db49b9612e97e29bbd933b550f156d2ea4de3e6.tar.gz rust-7db49b9612e97e29bbd933b550f156d2ea4de3e6.zip | |
Deduplicated borrow checking errors.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_mir/borrow_check.rs | 39 |
1 files changed, 29 insertions, 10 deletions
diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index f5f7b53a235..1c2289c758d 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -20,6 +20,7 @@ use rustc::mir::{Mir, Mutability, Operand, Projection, ProjectionElem, Rvalue}; use rustc::mir::{Statement, StatementKind, Terminator, TerminatorKind}; use transform::nll; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_set::{self, IdxSetBuf}; use rustc_data_structures::indexed_vec::{Idx}; @@ -136,6 +137,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, node_id: id, move_data: &mdpe.move_data, param_env: param_env, + storage_drop_or_dead_error_reported: FxHashSet(), }; let mut state = InProgress::new(flow_borrows, @@ -153,6 +155,10 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> { node_id: ast::NodeId, move_data: &'cx MoveData<'tcx>, param_env: ParamEnv<'gcx>, + /// This field keeps track of when storage drop or dead errors are reported + /// in order to stop duplicate error reporting and identify the conditions required + /// for a "temporary value dropped here while still borrowed" error. See #45360. + storage_drop_or_dead_error_reported: FxHashSet<Local>, } // (forced to be `pub` due to its use as an associated type below.) @@ -281,10 +287,12 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx } StatementKind::StorageDead(local) => { - self.access_lvalue(ContextKind::StorageDead.new(location), - (&Lvalue::Local(local), span), - (Shallow(None), Write(WriteKind::StorageDead)), - flow_state); + if self.storage_drop_or_dead_error_reported.insert(local) { + self.access_lvalue(ContextKind::StorageDead.new(location), + (&Lvalue::Local(local), span), + (Shallow(None), Write(WriteKind::StorageDead)), + flow_state); + } } } } @@ -604,12 +612,23 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let erased_ty = gcx.lift(&self.tcx.erase_regions(&ty)).unwrap(); let moves_by_default = erased_ty.moves_by_default(gcx, self.param_env, DUMMY_SP); - if moves_by_default { - // move of lvalue: check if this is move of already borrowed path - self.access_lvalue(context, lvalue_span, (Deep, Write(WriteKind::Move)), flow_state); - } else { - // copy of lvalue: check if this is "copy of frozen path" (FIXME: see check_loans.rs) - self.access_lvalue(context, lvalue_span, (Deep, Read(ReadKind::Copy)), flow_state); + // Check if error has already been reported to stop duplicate reporting. + let has_storage_drop_or_dead_error_reported = match *lvalue { + Lvalue::Local(local) => self.storage_drop_or_dead_error_reported.insert(local), + _ => false, + }; + + if !has_storage_drop_or_dead_error_reported { + if moves_by_default { + // move of lvalue: check if this is move of already borrowed path + self.access_lvalue(context, lvalue_span, (Deep, Write(WriteKind::Move)), + flow_state); + } else { + // copy of lvalue: check if this is "copy of frozen path" + // (FIXME: see check_loans.rs) + self.access_lvalue(context, lvalue_span, (Deep, Read(ReadKind::Copy)), + flow_state); + } } // Finally, check if path was already moved. |
