@@ -27,7 +27,7 @@ use rustc::ty::{self, ParamEnv, TyCtxt, Ty};
2727
2828use rustc_errors:: { Applicability , Diagnostic , DiagnosticBuilder , Level } ;
2929use rustc_data_structures:: bit_set:: BitSet ;
30- use rustc_data_structures:: fx:: FxHashSet ;
30+ use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
3131use rustc_data_structures:: graph:: dominators:: Dominators ;
3232use rustc_data_structures:: indexed_vec:: Idx ;
3333use smallvec:: SmallVec ;
@@ -38,6 +38,7 @@ use syntax_pos::Span;
3838
3939use dataflow:: indexes:: BorrowIndex ;
4040use dataflow:: move_paths:: { HasMoveData , LookupResult , MoveData , MoveError , MovePathIndex } ;
41+ use dataflow:: move_paths:: indexes:: MoveOutIndex ;
4142use dataflow:: Borrows ;
4243use dataflow:: DataflowResultsConsumer ;
4344use dataflow:: FlowAtLocation ;
@@ -255,7 +256,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
255256 locals_are_invalidated_at_exit,
256257 access_place_error_reported : FxHashSet ( ) ,
257258 reservation_error_reported : FxHashSet ( ) ,
258- moved_error_reported : FxHashSet ( ) ,
259+ move_error_reported : FxHashMap ( ) ,
260+ uninitialized_error_reported : FxHashSet ( ) ,
259261 errors_buffer,
260262 nonlexical_regioncx : regioncx,
261263 used_mut : FxHashSet ( ) ,
@@ -333,6 +335,11 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
333335 }
334336 }
335337
338+ // Buffer any move errors that we collected and de-duplicated.
339+ for ( _, ( _, diag) ) in mbcx. move_error_reported . drain ( ) {
340+ diag. buffer ( & mut mbcx. errors_buffer ) ;
341+ }
342+
336343 if mbcx. errors_buffer . len ( ) > 0 {
337344 mbcx. errors_buffer . sort_by_key ( |diag| diag. span . primary_span ( ) ) ;
338345
@@ -408,9 +415,20 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
408415 /// but it is currently inconvenient to track down the BorrowIndex
409416 /// at the time we detect and report a reservation error.
410417 reservation_error_reported : FxHashSet < Place < ' tcx > > ,
411- /// This field keeps track of errors reported in the checking of moved variables,
418+ /// This field keeps track of move errors that are to be reported for given move indicies.
419+ ///
420+ /// There are situations where many errors can be reported for a single move out (see #53807)
421+ /// and we want only the best of those errors.
422+ ///
423+ /// The `report_use_of_moved_or_uninitialized` function checks this map and replaces the
424+ /// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of the
425+ /// `Place` of the previous most diagnostic. This happens instead of buffering the error. Once
426+ /// all move errors have been reported, any diagnostics in this map are added to the buffer
427+ /// to be emitted.
428+ move_error_reported : FxHashMap < Vec < MoveOutIndex > , ( Place < ' tcx > , DiagnosticBuilder < ' cx > ) > ,
429+ /// This field keeps track of errors reported in the checking of uninitialized variables,
412430 /// so that we don't report seemingly duplicate errors.
413- moved_error_reported : FxHashSet < Place < ' tcx > > ,
431+ uninitialized_error_reported : FxHashSet < Place < ' tcx > > ,
414432 /// Errors to be reported buffer
415433 errors_buffer : Vec < Diagnostic > ,
416434 /// This field keeps track of all the local variables that are declared mut and are mutated.
@@ -801,7 +819,7 @@ enum LocalMutationIsAllowed {
801819 No ,
802820}
803821
804- #[ derive( Copy , Clone ) ]
822+ #[ derive( Copy , Clone , Debug ) ]
805823enum InitializationRequiringAction {
806824 Update ,
807825 Borrow ,
0 commit comments