@@ -19,7 +19,7 @@ extern crate tracing;
1919
2020use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
2121use rustc_data_structures:: graph:: dominators:: Dominators ;
22- use rustc_errors:: { Diagnostic , DiagnosticBuilder } ;
22+ use rustc_errors:: DiagnosticBuilder ;
2323use rustc_hir as hir;
2424use rustc_hir:: def_id:: LocalDefId ;
2525use rustc_index:: bit_set:: { BitSet , ChunkedBitSet } ;
@@ -173,7 +173,7 @@ fn do_mir_borrowck<'tcx>(
173173 }
174174 }
175175
176- let mut errors = error:: BorrowckErrors :: new ( infcx . tcx ) ;
176+ let mut errors = error:: BorrowckErrors :: new ( ) ;
177177
178178 // Gather the upvars of a closure, if any.
179179 if let Some ( e) = input_body. tainted_by_errors {
@@ -2124,7 +2124,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
21242124 | WriteKind :: MutableBorrow ( BorrowKind :: Fake ) ,
21252125 ) => {
21262126 if self . is_mutable ( place. as_ref ( ) , is_local_mutation_allowed) . is_err ( )
2127- && !self . has_buffered_errors ( )
2127+ && !self . has_buffered_diags ( )
21282128 {
21292129 // rust-lang/rust#46908: In pure NLL mode this code path should be
21302130 // unreachable, but we use `span_delayed_bug` because we can hit this when
@@ -2387,12 +2387,25 @@ mod error {
23872387
23882388 use super :: * ;
23892389
2390+ enum BufferedDiag < ' tcx > {
2391+ Error ( DiagnosticBuilder < ' tcx > ) ,
2392+ NonError ( DiagnosticBuilder < ' tcx , ( ) > ) ,
2393+ }
2394+
2395+ impl < ' tcx > BufferedDiag < ' tcx > {
2396+ fn sort_span ( & self ) -> Span {
2397+ match self {
2398+ BufferedDiag :: Error ( diag) => diag. sort_span ,
2399+ BufferedDiag :: NonError ( diag) => diag. sort_span ,
2400+ }
2401+ }
2402+ }
2403+
23902404 pub struct BorrowckErrors < ' tcx > {
2391- tcx : TyCtxt < ' tcx > ,
23922405 /// This field keeps track of move errors that are to be reported for given move indices.
23932406 ///
2394- /// There are situations where many errors can be reported for a single move out (see #53807)
2395- /// and we want only the best of those errors.
2407+ /// There are situations where many errors can be reported for a single move out (see
2408+ /// #53807) and we want only the best of those errors.
23962409 ///
23972410 /// The `report_use_of_moved_or_uninitialized` function checks this map and replaces the
23982411 /// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of
@@ -2405,46 +2418,37 @@ mod error {
24052418 /// same primary span come out in a consistent order.
24062419 buffered_move_errors :
24072420 BTreeMap < Vec < MoveOutIndex > , ( PlaceRef < ' tcx > , DiagnosticBuilder < ' tcx > ) > ,
2421+
24082422 buffered_mut_errors : FxIndexMap < Span , ( DiagnosticBuilder < ' tcx > , usize ) > ,
2409- /// Buffer of diagnostics to be reported. Uses `Diagnostic` rather than `DiagnosticBuilder`
2410- /// because it has a mixture of error diagnostics and non-error diagnostics.
2411- buffered : Vec < Diagnostic > ,
2412- /// Set to Some if we emit an error during borrowck
2413- tainted_by_errors : Option < ErrorGuaranteed > ,
2423+
2424+ /// Buffer of diagnostics to be reported. A mixture of error and non-error diagnostics.
2425+ buffered_diags : Vec < BufferedDiag < ' tcx > > ,
24142426 }
24152427
24162428 impl < ' tcx > BorrowckErrors < ' tcx > {
2417- pub fn new ( tcx : TyCtxt < ' tcx > ) -> Self {
2429+ pub fn new ( ) -> Self {
24182430 BorrowckErrors {
2419- tcx,
24202431 buffered_move_errors : BTreeMap :: new ( ) ,
24212432 buffered_mut_errors : Default :: default ( ) ,
2422- buffered : Default :: default ( ) ,
2423- tainted_by_errors : None ,
2433+ buffered_diags : Default :: default ( ) ,
24242434 }
24252435 }
24262436
2427- pub fn buffer_error ( & mut self , t : DiagnosticBuilder < ' _ > ) {
2428- if let None = self . tainted_by_errors {
2429- self . tainted_by_errors = Some ( self . tcx . dcx ( ) . span_delayed_bug (
2430- t. span . clone_ignoring_labels ( ) ,
2431- "diagnostic buffered but not emitted" ,
2432- ) )
2433- }
2434- self . buffered . push ( t. into_diagnostic ( ) ) ;
2437+ pub fn buffer_error ( & mut self , t : DiagnosticBuilder < ' tcx > ) {
2438+ self . buffered_diags . push ( BufferedDiag :: Error ( t) ) ;
24352439 }
24362440
2437- pub fn buffer_non_error ( & mut self , t : DiagnosticBuilder < ' _ , ( ) > ) {
2438- self . buffered . push ( t . into_diagnostic ( ) ) ;
2441+ pub fn buffer_non_error ( & mut self , t : DiagnosticBuilder < ' tcx , ( ) > ) {
2442+ self . buffered_diags . push ( BufferedDiag :: NonError ( t ) ) ;
24392443 }
24402444 }
24412445
24422446 impl < ' cx , ' tcx > MirBorrowckCtxt < ' cx , ' tcx > {
2443- pub fn buffer_error ( & mut self , t : DiagnosticBuilder < ' _ > ) {
2447+ pub fn buffer_error ( & mut self , t : DiagnosticBuilder < ' tcx > ) {
24442448 self . errors . buffer_error ( t) ;
24452449 }
24462450
2447- pub fn buffer_non_error ( & mut self , t : DiagnosticBuilder < ' _ , ( ) > ) {
2451+ pub fn buffer_non_error ( & mut self , t : DiagnosticBuilder < ' tcx , ( ) > ) {
24482452 self . errors . buffer_non_error ( t) ;
24492453 }
24502454
@@ -2476,38 +2480,41 @@ mod error {
24762480 }
24772481
24782482 pub fn emit_errors ( & mut self ) -> Option < ErrorGuaranteed > {
2483+ let mut res = None ;
2484+
24792485 // Buffer any move errors that we collected and de-duplicated.
24802486 for ( _, ( _, diag) ) in std:: mem:: take ( & mut self . errors . buffered_move_errors ) {
24812487 // We have already set tainted for this error, so just buffer it.
2482- self . errors . buffered . push ( diag . into_diagnostic ( ) ) ;
2488+ self . errors . buffered_diags . push ( BufferedDiag :: Error ( diag ) ) ;
24832489 }
24842490 for ( _, ( mut diag, count) ) in std:: mem:: take ( & mut self . errors . buffered_mut_errors ) {
24852491 if count > 10 {
24862492 diag. note ( format ! ( "...and {} other attempted mutable borrows" , count - 10 ) ) ;
24872493 }
2488- self . errors . buffered . push ( diag . into_diagnostic ( ) ) ;
2494+ self . errors . buffered_diags . push ( BufferedDiag :: Error ( diag ) ) ;
24892495 }
24902496
2491- if !self . errors . buffered . is_empty ( ) {
2492- self . errors . buffered . sort_by_key ( |diag| diag. sort_span ) ;
2493-
2494- let dcx = self . dcx ( ) ;
2495- for diag in self . errors . buffered . drain ( ..) {
2496- dcx. emit_diagnostic ( diag) ;
2497+ if !self . errors . buffered_diags . is_empty ( ) {
2498+ self . errors . buffered_diags . sort_by_key ( |buffered_diag| buffered_diag. sort_span ( ) ) ;
2499+ for buffered_diag in self . errors . buffered_diags . drain ( ..) {
2500+ match buffered_diag {
2501+ BufferedDiag :: Error ( diag) => res = Some ( diag. emit ( ) ) ,
2502+ BufferedDiag :: NonError ( diag) => diag. emit ( ) ,
2503+ }
24972504 }
24982505 }
24992506
2500- self . errors . tainted_by_errors
2507+ res
25012508 }
25022509
2503- pub fn has_buffered_errors ( & self ) -> bool {
2504- self . errors . buffered . is_empty ( )
2510+ pub ( crate ) fn has_buffered_diags ( & self ) -> bool {
2511+ self . errors . buffered_diags . is_empty ( )
25052512 }
25062513
25072514 pub fn has_move_error (
25082515 & self ,
25092516 move_out_indices : & [ MoveOutIndex ] ,
2510- ) -> Option < & ( PlaceRef < ' tcx > , DiagnosticBuilder < ' cx > ) > {
2517+ ) -> Option < & ( PlaceRef < ' tcx > , DiagnosticBuilder < ' tcx > ) > {
25112518 self . errors . buffered_move_errors . get ( move_out_indices)
25122519 }
25132520 }
0 commit comments