@@ -33,11 +33,13 @@ use rustc_data_structures::indexed_vec::Idx;
33
33
use smallvec:: SmallVec ;
34
34
35
35
use std:: rc:: Rc ;
36
+ use std:: collections:: BTreeMap ;
36
37
37
38
use syntax_pos:: Span ;
38
39
39
40
use dataflow:: indexes:: BorrowIndex ;
40
41
use dataflow:: move_paths:: { HasMoveData , LookupResult , MoveData , MoveError , MovePathIndex } ;
42
+ use dataflow:: move_paths:: indexes:: MoveOutIndex ;
41
43
use dataflow:: Borrows ;
42
44
use dataflow:: DataflowResultsConsumer ;
43
45
use dataflow:: FlowAtLocation ;
@@ -255,7 +257,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
255
257
locals_are_invalidated_at_exit,
256
258
access_place_error_reported : FxHashSet ( ) ,
257
259
reservation_error_reported : FxHashSet ( ) ,
258
- moved_error_reported : FxHashSet ( ) ,
260
+ move_error_reported : BTreeMap :: new ( ) ,
261
+ uninitialized_error_reported : FxHashSet ( ) ,
259
262
errors_buffer,
260
263
nonlexical_regioncx : regioncx,
261
264
used_mut : FxHashSet ( ) ,
@@ -333,6 +336,11 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
333
336
}
334
337
}
335
338
339
+ // Buffer any move errors that we collected and de-duplicated.
340
+ for ( _, ( _, diag) ) in mbcx. move_error_reported {
341
+ diag. buffer ( & mut mbcx. errors_buffer ) ;
342
+ }
343
+
336
344
if mbcx. errors_buffer . len ( ) > 0 {
337
345
mbcx. errors_buffer . sort_by_key ( |diag| diag. span . primary_span ( ) ) ;
338
346
@@ -408,9 +416,24 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
408
416
/// but it is currently inconvenient to track down the BorrowIndex
409
417
/// at the time we detect and report a reservation error.
410
418
reservation_error_reported : FxHashSet < Place < ' tcx > > ,
411
- /// This field keeps track of errors reported in the checking of moved variables,
419
+ /// This field keeps track of move errors that are to be reported for given move indicies.
420
+ ///
421
+ /// There are situations where many errors can be reported for a single move out (see #53807)
422
+ /// and we want only the best of those errors.
423
+ ///
424
+ /// The `report_use_of_moved_or_uninitialized` function checks this map and replaces the
425
+ /// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of the
426
+ /// `Place` of the previous most diagnostic. This happens instead of buffering the error. Once
427
+ /// all move errors have been reported, any diagnostics in this map are added to the buffer
428
+ /// to be emitted.
429
+ ///
430
+ /// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary
431
+ /// when errors in the map are being re-added to the error buffer so that errors with the
432
+ /// same primary span come out in a consistent order.
433
+ move_error_reported : BTreeMap < Vec < MoveOutIndex > , ( Place < ' tcx > , DiagnosticBuilder < ' cx > ) > ,
434
+ /// This field keeps track of errors reported in the checking of uninitialized variables,
412
435
/// so that we don't report seemingly duplicate errors.
413
- moved_error_reported : FxHashSet < Place < ' tcx > > ,
436
+ uninitialized_error_reported : FxHashSet < Place < ' tcx > > ,
414
437
/// Errors to be reported buffer
415
438
errors_buffer : Vec < Diagnostic > ,
416
439
/// This field keeps track of all the local variables that are declared mut and are mutated.
@@ -801,7 +824,7 @@ enum LocalMutationIsAllowed {
801
824
No ,
802
825
}
803
826
804
- #[ derive( Copy , Clone ) ]
827
+ #[ derive( Copy , Clone , Debug ) ]
805
828
enum InitializationRequiringAction {
806
829
Update ,
807
830
Borrow ,
0 commit comments