@@ -476,9 +476,10 @@ struct DiagCtxtInner {
476
476
emitted_diagnostics : FxHashSet < Hash128 > ,
477
477
478
478
/// Stashed diagnostics emitted in one stage of the compiler that may be
479
- /// stolen by other stages (e.g. to improve them and add more information).
480
- /// The stashed diagnostics count towards the total error count.
481
- /// When `.abort_if_errors()` is called, these are also emitted.
479
+ /// stolen and emitted/cancelled by other stages (e.g. to improve them and
480
+ /// add more information). All stashed diagnostics must be emitted with
481
+ /// `emit_stashed_diagnostics` by the time the `DiagCtxtInner` is dropped,
482
+ /// otherwise an assertion failure will occur.
482
483
stashed_diagnostics : FxIndexMap < ( Span , StashKey ) , Diagnostic > ,
483
484
484
485
future_breakage_diagnostics : Vec < Diagnostic > ,
@@ -563,7 +564,9 @@ pub struct DiagCtxtFlags {
563
564
564
565
impl Drop for DiagCtxtInner {
565
566
fn drop ( & mut self ) {
566
- self . emit_stashed_diagnostics ( ) ;
567
+ // Any stashed diagnostics should have been handled by
568
+ // `emit_stashed_diagnostics` by now.
569
+ assert ! ( self . stashed_diagnostics. is_empty( ) ) ;
567
570
568
571
if self . err_guars . is_empty ( ) {
569
572
self . flush_delayed ( )
@@ -755,17 +758,24 @@ impl DiagCtxt {
755
758
}
756
759
757
760
/// Emit all stashed diagnostics.
758
- pub fn emit_stashed_diagnostics ( & self ) {
761
+ pub fn emit_stashed_diagnostics ( & self ) -> Option < ErrorGuaranteed > {
759
762
self . inner . borrow_mut ( ) . emit_stashed_diagnostics ( )
760
763
}
761
764
762
- /// This excludes lint errors, delayed bugs, and stashed errors.
765
+ /// This excludes lint errors, delayed bugs and stashed errors.
763
766
#[ inline]
764
- pub fn err_count ( & self ) -> usize {
767
+ pub fn err_count_excluding_lint_errs ( & self ) -> usize {
765
768
self . inner . borrow ( ) . err_guars . len ( )
766
769
}
767
770
768
- /// This excludes normal errors, lint errors and delayed bugs. Unless
771
+ /// This excludes delayed bugs and stashed errors.
772
+ #[ inline]
773
+ pub fn err_count ( & self ) -> usize {
774
+ let inner = self . inner . borrow ( ) ;
775
+ inner. err_guars . len ( ) + inner. lint_err_guars . len ( )
776
+ }
777
+
778
+ /// This excludes normal errors, lint errors, and delayed bugs. Unless
769
779
/// absolutely necessary, avoid using this. It's dubious because stashed
770
780
/// errors can later be cancelled, so the presence of a stashed error at
771
781
/// some point of time doesn't guarantee anything -- there are no
@@ -774,27 +784,29 @@ impl DiagCtxt {
774
784
self . inner . borrow ( ) . stashed_err_count
775
785
}
776
786
777
- /// This excludes lint errors, delayed bugs, and stashed errors.
778
- pub fn has_errors ( & self ) -> Option < ErrorGuaranteed > {
779
- self . inner . borrow ( ) . has_errors ( )
787
+ /// This excludes lint errors, delayed bugs, and stashed errors. Unless
788
+ /// absolutely necessary, prefer `has_errors` to this method.
789
+ pub fn has_errors_excluding_lint_errors ( & self ) -> Option < ErrorGuaranteed > {
790
+ self . inner . borrow ( ) . has_errors_excluding_lint_errors ( )
780
791
}
781
792
782
- /// This excludes delayed bugs and stashed errors. Unless absolutely
783
- /// necessary, prefer `has_errors` to this method.
784
- pub fn has_errors_or_lint_errors ( & self ) -> Option < ErrorGuaranteed > {
785
- self . inner . borrow ( ) . has_errors_or_lint_errors ( )
793
+ /// This excludes delayed bugs and stashed errors.
794
+ pub fn has_errors ( & self ) -> Option < ErrorGuaranteed > {
795
+ self . inner . borrow ( ) . has_errors ( )
786
796
}
787
797
788
798
/// This excludes stashed errors. Unless absolutely necessary, prefer
789
- /// `has_errors` or `has_errors_or_lint_errors` to this method.
790
- pub fn has_errors_or_lint_errors_or_delayed_bugs ( & self ) -> Option < ErrorGuaranteed > {
791
- self . inner . borrow ( ) . has_errors_or_lint_errors_or_delayed_bugs ( )
799
+ /// `has_errors` to this method.
800
+ pub fn has_errors_or_delayed_bugs ( & self ) -> Option < ErrorGuaranteed > {
801
+ self . inner . borrow ( ) . has_errors_or_delayed_bugs ( )
792
802
}
793
803
794
804
pub fn print_error_count ( & self , registry : & Registry ) {
795
805
let mut inner = self . inner . borrow_mut ( ) ;
796
806
797
- inner. emit_stashed_diagnostics ( ) ;
807
+ // Any stashed diagnostics should have been handled by
808
+ // `emit_stashed_diagnostics` by now.
809
+ assert ! ( inner. stashed_diagnostics. is_empty( ) ) ;
798
810
799
811
if inner. treat_err_as_bug ( ) {
800
812
return ;
@@ -869,10 +881,12 @@ impl DiagCtxt {
869
881
}
870
882
}
871
883
884
+ /// This excludes delayed bugs and stashed errors. Used for early aborts
885
+ /// after errors occurred -- e.g. because continuing in the face of errors is
886
+ /// likely to lead to bad results, such as spurious/uninteresting
887
+ /// additional errors -- when returning an error `Result` is difficult.
872
888
pub fn abort_if_errors ( & self ) {
873
- let mut inner = self . inner . borrow_mut ( ) ;
874
- inner. emit_stashed_diagnostics ( ) ;
875
- if !inner. err_guars . is_empty ( ) {
889
+ if self . has_errors ( ) . is_some ( ) {
876
890
FatalError . raise ( ) ;
877
891
}
878
892
}
@@ -1273,10 +1287,10 @@ impl DiagCtxt {
1273
1287
// `DiagCtxtInner::foo`.
1274
1288
impl DiagCtxtInner {
1275
1289
/// Emit all stashed diagnostics.
1276
- fn emit_stashed_diagnostics ( & mut self ) {
1290
+ fn emit_stashed_diagnostics ( & mut self ) -> Option < ErrorGuaranteed > {
1291
+ let mut guar = None ;
1277
1292
let has_errors = !self . err_guars . is_empty ( ) ;
1278
1293
for ( _, diag) in std:: mem:: take ( & mut self . stashed_diagnostics ) . into_iter ( ) {
1279
- // Decrement the count tracking the stash; emitting will increment it.
1280
1294
if diag. is_error ( ) {
1281
1295
if diag. is_lint . is_none ( ) {
1282
1296
self . stashed_err_count -= 1 ;
@@ -1289,8 +1303,9 @@ impl DiagCtxtInner {
1289
1303
continue ;
1290
1304
}
1291
1305
}
1292
- self . emit_diagnostic ( diag) ;
1306
+ guar = guar . or ( self . emit_diagnostic ( diag) ) ;
1293
1307
}
1308
+ guar
1294
1309
}
1295
1310
1296
1311
// Return value is only `Some` if the level is `Error` or `DelayedBug`.
@@ -1334,7 +1349,7 @@ impl DiagCtxtInner {
1334
1349
DelayedBug => {
1335
1350
// If we have already emitted at least one error, we don't need
1336
1351
// to record the delayed bug, because it'll never be used.
1337
- return if let Some ( guar) = self . has_errors_or_lint_errors ( ) {
1352
+ return if let Some ( guar) = self . has_errors ( ) {
1338
1353
Some ( guar)
1339
1354
} else {
1340
1355
let backtrace = std:: backtrace:: Backtrace :: capture ( ) ;
@@ -1451,17 +1466,16 @@ impl DiagCtxtInner {
1451
1466
. is_some_and ( |c| self . err_guars . len ( ) + self . lint_err_guars . len ( ) + 1 >= c. get ( ) )
1452
1467
}
1453
1468
1454
- fn has_errors ( & self ) -> Option < ErrorGuaranteed > {
1469
+ fn has_errors_excluding_lint_errors ( & self ) -> Option < ErrorGuaranteed > {
1455
1470
self . err_guars . get ( 0 ) . copied ( )
1456
1471
}
1457
1472
1458
- fn has_errors_or_lint_errors ( & self ) -> Option < ErrorGuaranteed > {
1459
- self . has_errors ( ) . or_else ( || self . lint_err_guars . get ( 0 ) . copied ( ) )
1473
+ fn has_errors ( & self ) -> Option < ErrorGuaranteed > {
1474
+ self . has_errors_excluding_lint_errors ( ) . or_else ( || self . lint_err_guars . get ( 0 ) . copied ( ) )
1460
1475
}
1461
1476
1462
- fn has_errors_or_lint_errors_or_delayed_bugs ( & self ) -> Option < ErrorGuaranteed > {
1463
- self . has_errors_or_lint_errors ( )
1464
- . or_else ( || self . delayed_bugs . get ( 0 ) . map ( |( _, guar) | guar) . copied ( ) )
1477
+ fn has_errors_or_delayed_bugs ( & self ) -> Option < ErrorGuaranteed > {
1478
+ self . has_errors ( ) . or_else ( || self . delayed_bugs . get ( 0 ) . map ( |( _, guar) | guar) . copied ( ) )
1465
1479
}
1466
1480
1467
1481
/// Translate `message` eagerly with `args` to `SubdiagnosticMessage::Eager`.
@@ -1484,6 +1498,11 @@ impl DiagCtxtInner {
1484
1498
}
1485
1499
1486
1500
fn flush_delayed ( & mut self ) {
1501
+ // Stashed diagnostics must be emitted before delayed bugs are flushed.
1502
+ // Otherwise, we might ICE prematurely when errors would have
1503
+ // eventually happened.
1504
+ assert ! ( self . stashed_diagnostics. is_empty( ) ) ;
1505
+
1487
1506
if self . delayed_bugs . is_empty ( ) {
1488
1507
return ;
1489
1508
}
0 commit comments