@@ -19,7 +19,7 @@ extern crate tracing;
19
19
20
20
use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
21
21
use rustc_data_structures:: graph:: dominators:: Dominators ;
22
- use rustc_errors:: { Diagnostic , DiagnosticBuilder } ;
22
+ use rustc_errors:: DiagnosticBuilder ;
23
23
use rustc_hir as hir;
24
24
use rustc_hir:: def_id:: LocalDefId ;
25
25
use rustc_index:: bit_set:: { BitSet , ChunkedBitSet } ;
@@ -173,7 +173,7 @@ fn do_mir_borrowck<'tcx>(
173
173
}
174
174
}
175
175
176
- let mut errors = error:: BorrowckErrors :: new ( infcx . tcx ) ;
176
+ let mut errors = error:: BorrowckErrors :: new ( ) ;
177
177
178
178
// Gather the upvars of a closure, if any.
179
179
if let Some ( e) = input_body. tainted_by_errors {
@@ -2124,7 +2124,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
2124
2124
| WriteKind :: MutableBorrow ( BorrowKind :: Fake ) ,
2125
2125
) => {
2126
2126
if self . is_mutable ( place. as_ref ( ) , is_local_mutation_allowed) . is_err ( )
2127
- && !self . has_buffered_errors ( )
2127
+ && !self . has_buffered_diags ( )
2128
2128
{
2129
2129
// rust-lang/rust#46908: In pure NLL mode this code path should be
2130
2130
// unreachable, but we use `span_delayed_bug` because we can hit this when
@@ -2387,12 +2387,25 @@ mod error {
2387
2387
2388
2388
use super :: * ;
2389
2389
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
+
2390
2404
pub struct BorrowckErrors < ' tcx > {
2391
- tcx : TyCtxt < ' tcx > ,
2392
2405
/// This field keeps track of move errors that are to be reported for given move indices.
2393
2406
///
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.
2396
2409
///
2397
2410
/// The `report_use_of_moved_or_uninitialized` function checks this map and replaces the
2398
2411
/// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of
@@ -2405,46 +2418,37 @@ mod error {
2405
2418
/// same primary span come out in a consistent order.
2406
2419
buffered_move_errors :
2407
2420
BTreeMap < Vec < MoveOutIndex > , ( PlaceRef < ' tcx > , DiagnosticBuilder < ' tcx > ) > ,
2421
+
2408
2422
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 > > ,
2414
2426
}
2415
2427
2416
2428
impl < ' tcx > BorrowckErrors < ' tcx > {
2417
- pub fn new ( tcx : TyCtxt < ' tcx > ) -> Self {
2429
+ pub fn new ( ) -> Self {
2418
2430
BorrowckErrors {
2419
- tcx,
2420
2431
buffered_move_errors : BTreeMap :: new ( ) ,
2421
2432
buffered_mut_errors : Default :: default ( ) ,
2422
- buffered : Default :: default ( ) ,
2423
- tainted_by_errors : None ,
2433
+ buffered_diags : Default :: default ( ) ,
2424
2434
}
2425
2435
}
2426
2436
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) ) ;
2435
2439
}
2436
2440
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 ) ) ;
2439
2443
}
2440
2444
}
2441
2445
2442
2446
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 > ) {
2444
2448
self . errors . buffer_error ( t) ;
2445
2449
}
2446
2450
2447
- pub fn buffer_non_error ( & mut self , t : DiagnosticBuilder < ' _ , ( ) > ) {
2451
+ pub fn buffer_non_error ( & mut self , t : DiagnosticBuilder < ' tcx , ( ) > ) {
2448
2452
self . errors . buffer_non_error ( t) ;
2449
2453
}
2450
2454
@@ -2476,38 +2480,41 @@ mod error {
2476
2480
}
2477
2481
2478
2482
pub fn emit_errors ( & mut self ) -> Option < ErrorGuaranteed > {
2483
+ let mut res = None ;
2484
+
2479
2485
// Buffer any move errors that we collected and de-duplicated.
2480
2486
for ( _, ( _, diag) ) in std:: mem:: take ( & mut self . errors . buffered_move_errors ) {
2481
2487
// 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 ) ) ;
2483
2489
}
2484
2490
for ( _, ( mut diag, count) ) in std:: mem:: take ( & mut self . errors . buffered_mut_errors ) {
2485
2491
if count > 10 {
2486
2492
diag. note ( format ! ( "...and {} other attempted mutable borrows" , count - 10 ) ) ;
2487
2493
}
2488
- self . errors . buffered . push ( diag . into_diagnostic ( ) ) ;
2494
+ self . errors . buffered_diags . push ( BufferedDiag :: Error ( diag ) ) ;
2489
2495
}
2490
2496
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
+ }
2497
2504
}
2498
2505
}
2499
2506
2500
- self . errors . tainted_by_errors
2507
+ res
2501
2508
}
2502
2509
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 ( )
2505
2512
}
2506
2513
2507
2514
pub fn has_move_error (
2508
2515
& self ,
2509
2516
move_out_indices : & [ MoveOutIndex ] ,
2510
- ) -> Option < & ( PlaceRef < ' tcx > , DiagnosticBuilder < ' cx > ) > {
2517
+ ) -> Option < & ( PlaceRef < ' tcx > , DiagnosticBuilder < ' tcx > ) > {
2511
2518
self . errors . buffered_move_errors . get ( move_out_indices)
2512
2519
}
2513
2520
}
0 commit comments