未验证 提交 783bad42 编写于 作者: D David Wood

De-duplicate moved variable errors.

By introducing a new map that tracks the errors reported and the
`Place`s that spawned those errors against the move out that the error
was referring to, we are able to silence duplicate errors by emitting
only the error which corresponds to the most specific `Place` (that which
other `Place`s which reported errors are prefixes of).

This generally is an improvement, however there is a case -
`liveness-move-in-while` - where the output regresses.
上级 874e08bd
......@@ -38,6 +38,12 @@ pub(super) fn report_use_of_moved_or_uninitialized(
(place, span): (&Place<'tcx>, Span),
mpi: MovePathIndex,
) {
debug!(
"report_use_of_moved_or_uninitialized: context={:?} desired_action={:?} place={:?} \
span={:?} mpi={:?}",
context, desired_action, place, span, mpi
);
let use_spans = self
.move_spans(place, context.loc)
.or_else(|| self.borrow_spans(span, context.loc));
......@@ -49,7 +55,7 @@ pub(super) fn report_use_of_moved_or_uninitialized(
if mois.is_empty() {
let root_place = self.prefixes(&place, PrefixSet::All).last().unwrap();
if self.moved_error_reported.contains(&root_place.clone()) {
if self.uninitialized_error_reported.contains(&root_place.clone()) {
debug!(
"report_use_of_moved_or_uninitialized place: error about {:?} suppressed",
root_place
......@@ -57,7 +63,7 @@ pub(super) fn report_use_of_moved_or_uninitialized(
return;
}
self.moved_error_reported.insert(root_place.clone());
self.uninitialized_error_reported.insert(root_place.clone());
let item_msg = match self.describe_place_with_options(place, IncludingDowncast(true)) {
Some(name) => format!("`{}`", name),
......@@ -80,6 +86,14 @@ pub(super) fn report_use_of_moved_or_uninitialized(
err.buffer(&mut self.errors_buffer);
} else {
if let Some((reported_place, _)) = self.move_error_reported.get(&mois) {
if self.prefixes(&reported_place, PrefixSet::All).any(|p| p == place) {
debug!("report_use_of_moved_or_uninitialized place: error suppressed \
mois={:?}", mois);
return;
}
}
let msg = ""; //FIXME: add "partially " or "collaterally "
let mut err = self.tcx.cannot_act_on_moved_value(
......@@ -167,7 +181,13 @@ pub(super) fn report_use_of_moved_or_uninitialized(
}
}
err.buffer(&mut self.errors_buffer);
if let Some((_, mut old_err)) = self.move_error_reported.insert(
mois,
(place.clone(), err)
) {
// Cancel the old error so it doesn't ICE.
old_err.cancel();
}
}
}
......
......@@ -27,7 +27,7 @@
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, Level};
use rustc_data_structures::bit_set::BitSet;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::graph::dominators::Dominators;
use rustc_data_structures::indexed_vec::Idx;
use smallvec::SmallVec;
......@@ -38,6 +38,7 @@
use dataflow::indexes::BorrowIndex;
use dataflow::move_paths::{HasMoveData, LookupResult, MoveData, MoveError, MovePathIndex};
use dataflow::move_paths::indexes::MoveOutIndex;
use dataflow::Borrows;
use dataflow::DataflowResultsConsumer;
use dataflow::FlowAtLocation;
......@@ -255,7 +256,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
locals_are_invalidated_at_exit,
access_place_error_reported: FxHashSet(),
reservation_error_reported: FxHashSet(),
moved_error_reported: FxHashSet(),
move_error_reported: FxHashMap(),
uninitialized_error_reported: FxHashSet(),
errors_buffer,
nonlexical_regioncx: regioncx,
used_mut: FxHashSet(),
......@@ -333,6 +335,11 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
}
}
// Buffer any move errors that we collected and de-duplicated.
for (_, (_, diag)) in mbcx.move_error_reported.drain() {
diag.buffer(&mut mbcx.errors_buffer);
}
if mbcx.errors_buffer.len() > 0 {
mbcx.errors_buffer.sort_by_key(|diag| diag.span.primary_span());
......@@ -408,9 +415,20 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
/// but it is currently inconvenient to track down the BorrowIndex
/// at the time we detect and report a reservation error.
reservation_error_reported: FxHashSet<Place<'tcx>>,
/// This field keeps track of errors reported in the checking of moved variables,
/// This field keeps track of move errors that are to be reported for given move indicies.
///
/// There are situations where many errors can be reported for a single move out (see #53807)
/// and we want only the best of those errors.
///
/// The `report_use_of_moved_or_uninitialized` function checks this map and replaces the
/// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of the
/// `Place` of the previous most diagnostic. This happens instead of buffering the error. Once
/// all move errors have been reported, any diagnostics in this map are added to the buffer
/// to be emitted.
move_error_reported: FxHashMap<Vec<MoveOutIndex>, (Place<'tcx>, DiagnosticBuilder<'cx>)>,
/// This field keeps track of errors reported in the checking of uninitialized variables,
/// so that we don't report seemingly duplicate errors.
moved_error_reported: FxHashSet<Place<'tcx>>,
uninitialized_error_reported: FxHashSet<Place<'tcx>>,
/// Errors to be reported buffer
errors_buffer: Vec<Diagnostic>,
/// This field keeps track of all the local variables that are declared mut and are mutated.
......@@ -801,7 +819,7 @@ enum LocalMutationIsAllowed {
No,
}
#[derive(Copy, Clone)]
#[derive(Copy, Clone, Debug)]
enum InitializationRequiringAction {
Update,
Borrow,
......
......@@ -26,31 +26,31 @@ LL | drop(x2); //~ ERROR cannot move `x2` into closure because it is bor
LL | borrow(&*p2);
| ---- borrow later used here
error[E0382]: use of moved value: `x1`
error[E0382]: use of moved value: `x2`
--> $DIR/borrowck-multiple-captures.rs:35:19
|
LL | drop(x1);
LL | drop(x2);
| -- value moved here
...
LL | thread::spawn(move|| {
| ^^^^^^ value used here after move
LL | drop(x1); //~ ERROR capture of moved value: `x1`
LL | drop(x2); //~ ERROR capture of moved value: `x2`
| -- use occurs due to use in closure
|
= note: move occurs because `x1` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
= note: move occurs because `x2` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `x2`
error[E0382]: use of moved value: `x1`
--> $DIR/borrowck-multiple-captures.rs:35:19
|
LL | drop(x2);
LL | drop(x1);
| -- value moved here
...
LL | thread::spawn(move|| {
| ^^^^^^ value used here after move
LL | drop(x1); //~ ERROR capture of moved value: `x1`
LL | drop(x2); //~ ERROR capture of moved value: `x2`
| -- use occurs due to use in closure
|
= note: move occurs because `x2` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
= note: move occurs because `x1` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `x`
--> $DIR/borrowck-multiple-captures.rs:46:14
......
......@@ -18,9 +18,6 @@ pub fn main(){
}
//~^^ ERROR use of partially moved value: `maybe` (Ast) [E0382]
//~| ERROR use of moved value: `(maybe as std::prelude::v1::Some).0` (Ast) [E0382]
//~| ERROR use of moved value: `maybe` (Mir) [E0382]
//~| ERROR use of moved value: `maybe` (Mir) [E0382]
//~| ERROR use of moved value (Mir) [E0382]
//~| ERROR borrow of moved value: `maybe` (Mir) [E0382]
}
}
......@@ -16,17 +16,6 @@ LL | if let Some(thing) = maybe {
|
= note: move occurs because the value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `maybe` (Mir)
--> $DIR/issue-41962.rs:17:16
|
LL | if let Some(thing) = maybe {
| ^^^^^-----^
| | |
| | value moved here
| value used here after move
|
= note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
error[E0382]: use of moved value (Mir)
--> $DIR/issue-41962.rs:17:21
|
......@@ -35,26 +24,6 @@ LL | if let Some(thing) = maybe {
|
= note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `maybe` (Mir)
--> $DIR/issue-41962.rs:17:30
|
LL | if let Some(thing) = maybe {
| ----- ^^^^^ value used here after move
| |
| value moved here
|
= note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
error[E0382]: borrow of moved value: `maybe` (Mir)
--> $DIR/issue-41962.rs:17:30
|
LL | if let Some(thing) = maybe {
| ----- ^^^^^ value borrowed here after move
| |
| value moved here
|
= note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
error: aborting due to 6 previous errors
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0382`.
error[E0382]: use of moved value: `foo`
--> $DIR/issue-17385.rs:28:11
|
LL | drop(foo);
| --- value moved here
LL | match foo { //~ ERROR use of moved value
| ^^^ value used here after move
|
= note: move occurs because `foo` has type `X`, which does not implement the `Copy` trait
error[E0382]: borrow of moved value: `foo`
--> $DIR/issue-17385.rs:28:11
|
LL | drop(foo);
| --- value moved here
LL | match foo { //~ ERROR use of moved value
| ^^^ value borrowed here after move
|
= note: move occurs because `foo` has type `X`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `foo.0`
--> $DIR/issue-17385.rs:29:11
|
......@@ -39,27 +19,6 @@ LL | match e { //~ ERROR use of moved value
|
= note: move occurs because `e` has type `Enum`, which does not implement the `Copy` trait
error[E0382]: borrow of moved value: `e`
--> $DIR/issue-17385.rs:35:11
|
LL | drop(e);
| - value moved here
LL | match e { //~ ERROR use of moved value
| ^ value borrowed here after move
|
= note: move occurs because `e` has type `Enum`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `e`
--> $DIR/issue-17385.rs:36:9
|
LL | drop(e);
| - value moved here
LL | match e { //~ ERROR use of moved value
LL | Enum::Variant1 => unreachable!(),
| ^^^^^^^^^^^^^^ value used here after move
|
= note: move occurs because `e` has type `Enum`, which does not implement the `Copy` trait
error: aborting due to 6 previous errors
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0382`.
......@@ -8,14 +8,6 @@ LL | while true { while true { while true { x = y; x.clone(); } } }
|
= note: move occurs because `y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `y`
--> $DIR/liveness-move-in-while.rs:18:52
|
LL | while true { while true { while true { x = y; x.clone(); } } }
| ^ value moved here in previous iteration of loop
|
= note: move occurs because `y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
error: aborting due to 2 previous errors
error: aborting due to previous error
For more information about this error, try `rustc --explain E0382`.
error[E0382]: use of moved value
--> $DIR/issue-53807.rs:14:21
|
LL | if let Some(thing) = maybe {
| ^^^^^ value moved here in previous iteration of loop
|
= note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
error: aborting due to previous error
For more information about this error, try `rustc --explain E0382`.
// 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.
pub fn main(){
let maybe = Some(vec![true, true]);
loop {
if let Some(thing) = maybe {
}
}
}
error[E0382]: use of partially moved value: `maybe`
--> $DIR/issue-53807.rs:14:30
|
LL | if let Some(thing) = maybe {
| ----- ^^^^^ value used here after move
| |
| value moved here
|
= note: move occurs because the value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `(maybe as std::prelude::v1::Some).0`
--> $DIR/issue-53807.rs:14:21
|
LL | if let Some(thing) = maybe {
| ^^^^^ value moved here in previous iteration of loop
|
= note: move occurs because the value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0382`.
......@@ -11,19 +11,6 @@ LL | assert_eq!((*arc_v)[2], 3);
|
= note: move occurs because `arc_v` has type `std::sync::Arc<std::vec::Vec<i32>>`, which does not implement the `Copy` trait
error[E0382]: borrow of moved value: `arc_v`
--> $DIR/no-capture-arc.rs:26:23
|
LL | thread::spawn(move|| {
| ------ value moved into closure here
LL | assert_eq!((*arc_v)[3], 4);
| ----- variable moved due to use in closure
...
LL | println!("{:?}", *arc_v);
| ^^^^^ value borrowed here after move
|
= note: move occurs because `arc_v` has type `std::sync::Arc<std::vec::Vec<i32>>`, which does not implement the `Copy` trait
error: aborting due to 2 previous errors
error: aborting due to previous error
For more information about this error, try `rustc --explain E0382`.
......@@ -11,19 +11,6 @@ LL | assert_eq!((*arc_v)[2], 3); //~ ERROR use of moved value: `arc_v`
|
= note: move occurs because `arc_v` has type `std::sync::Arc<std::vec::Vec<i32>>`, which does not implement the `Copy` trait
error[E0382]: borrow of moved value: `arc_v`
--> $DIR/no-reuse-move-arc.rs:24:23
|
LL | thread::spawn(move|| {
| ------ value moved into closure here
LL | assert_eq!((*arc_v)[3], 4);
| ----- variable moved due to use in closure
...
LL | println!("{:?}", *arc_v); //~ ERROR use of moved value: `arc_v`
| ^^^^^ value borrowed here after move
|
= note: move occurs because `arc_v` has type `std::sync::Arc<std::vec::Vec<i32>>`, which does not implement the `Copy` trait
error: aborting due to 2 previous errors
error: aborting due to previous error
For more information about this error, try `rustc --explain E0382`.
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册