@@ -471,9 +471,10 @@ struct DiagCtxtInner {
471
471
emitted_diagnostics : FxHashSet < Hash128 > ,
472
472
473
473
/// Stashed diagnostics emitted in one stage of the compiler that may be
474
- /// stolen by other stages (e.g. to improve them and add more information).
475
- /// The stashed diagnostics count towards the total error count.
476
- /// When `.abort_if_errors()` is called, these are also emitted.
474
+ /// stolen and emitted/cancelled by other stages (e.g. to improve them and
475
+ /// add more information). All stashed diagnostics must be emitted with
476
+ /// `emit_stashed_diagnostics` by the time the `DiagCtxtInner` is dropped,
477
+ /// otherwise an assertion failure will occur.
477
478
stashed_diagnostics : FxIndexMap < ( Span , StashKey ) , Diagnostic > ,
478
479
479
480
future_breakage_diagnostics : Vec < Diagnostic > ,
@@ -558,7 +559,9 @@ pub struct DiagCtxtFlags {
558
559
559
560
impl Drop for DiagCtxtInner {
560
561
fn drop ( & mut self ) {
561
- self . emit_stashed_diagnostics ( ) ;
562
+ // Any stashed diagnostics should have been handled by
563
+ // `emit_stashed_diagnostics` by now.
564
+ assert ! ( self . stashed_diagnostics. is_empty( ) ) ;
562
565
563
566
if self . err_guars . is_empty ( ) {
564
567
self . flush_delayed ( )
@@ -750,17 +753,24 @@ impl DiagCtxt {
750
753
}
751
754
752
755
/// Emit all stashed diagnostics.
753
- pub fn emit_stashed_diagnostics ( & self ) {
756
+ pub fn emit_stashed_diagnostics ( & self ) -> Option < ErrorGuaranteed > {
754
757
self . inner . borrow_mut ( ) . emit_stashed_diagnostics ( )
755
758
}
756
759
757
- /// This excludes lint errors, delayed bugs, and stashed errors.
760
+ /// This excludes lint errors, delayed bugs and stashed errors.
758
761
#[ inline]
759
- pub fn err_count ( & self ) -> usize {
762
+ pub fn err_count_excluding_lint_errs ( & self ) -> usize {
760
763
self . inner . borrow ( ) . err_guars . len ( )
761
764
}
762
765
763
- /// This excludes normal errors, lint errors and delayed bugs. Unless
766
+ /// This excludes delayed bugs and stashed errors.
767
+ #[ inline]
768
+ pub fn err_count ( & self ) -> usize {
769
+ let inner = self . inner . borrow ( ) ;
770
+ inner. err_guars . len ( ) + inner. lint_err_guars . len ( )
771
+ }
772
+
773
+ /// This excludes normal errors, lint errors, and delayed bugs. Unless
764
774
/// absolutely necessary, avoid using this. It's dubious because stashed
765
775
/// errors can later be cancelled, so the presence of a stashed error at
766
776
/// some point of time doesn't guarantee anything -- there are no
@@ -769,27 +779,29 @@ impl DiagCtxt {
769
779
self . inner . borrow ( ) . stashed_err_count
770
780
}
771
781
772
- /// This excludes lint errors, delayed bugs, and stashed errors.
773
- pub fn has_errors ( & self ) -> Option < ErrorGuaranteed > {
774
- self . inner . borrow ( ) . has_errors ( )
782
+ /// This excludes lint errors, delayed bugs, and stashed errors. Unless
783
+ /// absolutely necessary, prefer `has_errors` to this method.
784
+ pub fn has_errors_excluding_lint_errors ( & self ) -> Option < ErrorGuaranteed > {
785
+ self . inner . borrow ( ) . has_errors_excluding_lint_errors ( )
775
786
}
776
787
777
- /// This excludes delayed bugs and stashed errors. Unless absolutely
778
- /// necessary, prefer `has_errors` to this method.
779
- pub fn has_errors_or_lint_errors ( & self ) -> Option < ErrorGuaranteed > {
780
- self . inner . borrow ( ) . has_errors_or_lint_errors ( )
788
+ /// This excludes delayed bugs and stashed errors.
789
+ pub fn has_errors ( & self ) -> Option < ErrorGuaranteed > {
790
+ self . inner . borrow ( ) . has_errors ( )
781
791
}
782
792
783
793
/// This excludes stashed errors. Unless absolutely necessary, prefer
784
- /// `has_errors` or `has_errors_or_lint_errors` to this method.
785
- pub fn has_errors_or_lint_errors_or_delayed_bugs ( & self ) -> Option < ErrorGuaranteed > {
786
- self . inner . borrow ( ) . has_errors_or_lint_errors_or_delayed_bugs ( )
794
+ /// `has_errors` to this method.
795
+ pub fn has_errors_or_delayed_bugs ( & self ) -> Option < ErrorGuaranteed > {
796
+ self . inner . borrow ( ) . has_errors_or_delayed_bugs ( )
787
797
}
788
798
789
799
pub fn print_error_count ( & self , registry : & Registry ) {
790
800
let mut inner = self . inner . borrow_mut ( ) ;
791
801
792
- inner. emit_stashed_diagnostics ( ) ;
802
+ // Any stashed diagnostics should have been handled by
803
+ // `emit_stashed_diagnostics` by now.
804
+ assert ! ( inner. stashed_diagnostics. is_empty( ) ) ;
793
805
794
806
if inner. treat_err_as_bug ( ) {
795
807
return ;
@@ -864,10 +876,12 @@ impl DiagCtxt {
864
876
}
865
877
}
866
878
879
+ /// This excludes delayed bugs and stashed errors. Used for early aborts
880
+ /// after errors occurred -- e.g. because continuing in the face of errors is
881
+ /// likely to lead to bad results, such as spurious/uninteresting
882
+ /// additional errors -- when returning an error `Result` is difficult.
867
883
pub fn abort_if_errors ( & self ) {
868
- let mut inner = self . inner . borrow_mut ( ) ;
869
- inner. emit_stashed_diagnostics ( ) ;
870
- if !inner. err_guars . is_empty ( ) {
884
+ if self . has_errors ( ) . is_some ( ) {
871
885
FatalError . raise ( ) ;
872
886
}
873
887
}
@@ -1268,10 +1282,10 @@ impl DiagCtxt {
1268
1282
// `DiagCtxtInner::foo`.
1269
1283
impl DiagCtxtInner {
1270
1284
/// Emit all stashed diagnostics.
1271
- fn emit_stashed_diagnostics ( & mut self ) {
1285
+ fn emit_stashed_diagnostics ( & mut self ) -> Option < ErrorGuaranteed > {
1286
+ let mut guar = None ;
1272
1287
let has_errors = !self . err_guars . is_empty ( ) ;
1273
1288
for ( _, diag) in std:: mem:: take ( & mut self . stashed_diagnostics ) . into_iter ( ) {
1274
- // Decrement the count tracking the stash; emitting will increment it.
1275
1289
if diag. is_error ( ) {
1276
1290
if diag. is_lint . is_none ( ) {
1277
1291
self . stashed_err_count -= 1 ;
@@ -1284,8 +1298,9 @@ impl DiagCtxtInner {
1284
1298
continue ;
1285
1299
}
1286
1300
}
1287
- self . emit_diagnostic ( diag) ;
1301
+ guar = guar . or ( self . emit_diagnostic ( diag) ) ;
1288
1302
}
1303
+ guar
1289
1304
}
1290
1305
1291
1306
// Return value is only `Some` if the level is `Error` or `DelayedBug`.
@@ -1329,7 +1344,7 @@ impl DiagCtxtInner {
1329
1344
DelayedBug => {
1330
1345
// If we have already emitted at least one error, we don't need
1331
1346
// to record the delayed bug, because it'll never be used.
1332
- return if let Some ( guar) = self . has_errors_or_lint_errors ( ) {
1347
+ return if let Some ( guar) = self . has_errors ( ) {
1333
1348
Some ( guar)
1334
1349
} else {
1335
1350
let backtrace = std:: backtrace:: Backtrace :: capture ( ) ;
@@ -1445,17 +1460,16 @@ impl DiagCtxtInner {
1445
1460
. is_some_and ( |c| self . err_guars . len ( ) + self . lint_err_guars . len ( ) + 1 >= c. get ( ) )
1446
1461
}
1447
1462
1448
- fn has_errors ( & self ) -> Option < ErrorGuaranteed > {
1463
+ fn has_errors_excluding_lint_errors ( & self ) -> Option < ErrorGuaranteed > {
1449
1464
self . err_guars . get ( 0 ) . copied ( )
1450
1465
}
1451
1466
1452
- fn has_errors_or_lint_errors ( & self ) -> Option < ErrorGuaranteed > {
1453
- self . has_errors ( ) . or_else ( || self . lint_err_guars . get ( 0 ) . copied ( ) )
1467
+ fn has_errors ( & self ) -> Option < ErrorGuaranteed > {
1468
+ self . has_errors_excluding_lint_errors ( ) . or_else ( || self . lint_err_guars . get ( 0 ) . copied ( ) )
1454
1469
}
1455
1470
1456
- fn has_errors_or_lint_errors_or_delayed_bugs ( & self ) -> Option < ErrorGuaranteed > {
1457
- self . has_errors_or_lint_errors ( )
1458
- . or_else ( || self . delayed_bugs . get ( 0 ) . map ( |( _, guar) | guar) . copied ( ) )
1471
+ fn has_errors_or_delayed_bugs ( & self ) -> Option < ErrorGuaranteed > {
1472
+ self . has_errors ( ) . or_else ( || self . delayed_bugs . get ( 0 ) . map ( |( _, guar) | guar) . copied ( ) )
1459
1473
}
1460
1474
1461
1475
/// Translate `message` eagerly with `args` to `SubdiagnosticMessage::Eager`.
@@ -1488,6 +1502,11 @@ impl DiagCtxtInner {
1488
1502
}
1489
1503
1490
1504
fn flush_delayed ( & mut self ) {
1505
+ // Stashed diagnostics must be emitted before delayed bugs are flushed.
1506
+ // Otherwise, we might ICE prematurely when errors would have
1507
+ // eventually happened.
1508
+ assert ! ( self . stashed_diagnostics. is_empty( ) ) ;
1509
+
1491
1510
if self . delayed_bugs . is_empty ( ) {
1492
1511
return ;
1493
1512
}
0 commit comments