@@ -476,9 +476,10 @@ struct DiagCtxtInner {
476476 emitted_diagnostics : FxHashSet < Hash128 > ,
477477
478478 /// 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.
482483 stashed_diagnostics : FxIndexMap < ( Span , StashKey ) , Diagnostic > ,
483484
484485 future_breakage_diagnostics : Vec < Diagnostic > ,
@@ -563,7 +564,9 @@ pub struct DiagCtxtFlags {
563564
564565impl Drop for DiagCtxtInner {
565566 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( ) ) ;
567570
568571 if self . err_guars . is_empty ( ) {
569572 self . flush_delayed ( )
@@ -755,17 +758,24 @@ impl DiagCtxt {
755758 }
756759
757760 /// Emit all stashed diagnostics.
758- pub fn emit_stashed_diagnostics ( & self ) {
761+ pub fn emit_stashed_diagnostics ( & self ) -> Option < ErrorGuaranteed > {
759762 self . inner . borrow_mut ( ) . emit_stashed_diagnostics ( )
760763 }
761764
762- /// This excludes lint errors, delayed bugs, and stashed errors.
765+ /// This excludes lint errors, delayed bugs and stashed errors.
763766 #[ inline]
764- pub fn err_count ( & self ) -> usize {
767+ pub fn err_count_excluding_lint_errs ( & self ) -> usize {
765768 self . inner . borrow ( ) . err_guars . len ( )
766769 }
767770
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
769779 /// absolutely necessary, avoid using this. It's dubious because stashed
770780 /// errors can later be cancelled, so the presence of a stashed error at
771781 /// some point of time doesn't guarantee anything -- there are no
@@ -774,27 +784,29 @@ impl DiagCtxt {
774784 self . inner . borrow ( ) . stashed_err_count
775785 }
776786
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 ( )
780791 }
781792
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 ( )
786796 }
787797
788798 /// 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 ( )
792802 }
793803
794804 pub fn print_error_count ( & self , registry : & Registry ) {
795805 let mut inner = self . inner . borrow_mut ( ) ;
796806
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( ) ) ;
798810
799811 if inner. treat_err_as_bug ( ) {
800812 return ;
@@ -869,10 +881,12 @@ impl DiagCtxt {
869881 }
870882 }
871883
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.
872888 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 ( ) {
876890 FatalError . raise ( ) ;
877891 }
878892 }
@@ -1273,10 +1287,10 @@ impl DiagCtxt {
12731287// `DiagCtxtInner::foo`.
12741288impl DiagCtxtInner {
12751289 /// 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 ;
12771292 let has_errors = !self . err_guars . is_empty ( ) ;
12781293 for ( _, diag) in std:: mem:: take ( & mut self . stashed_diagnostics ) . into_iter ( ) {
1279- // Decrement the count tracking the stash; emitting will increment it.
12801294 if diag. is_error ( ) {
12811295 if diag. is_lint . is_none ( ) {
12821296 self . stashed_err_count -= 1 ;
@@ -1289,8 +1303,9 @@ impl DiagCtxtInner {
12891303 continue ;
12901304 }
12911305 }
1292- self . emit_diagnostic ( diag) ;
1306+ guar = guar . or ( self . emit_diagnostic ( diag) ) ;
12931307 }
1308+ guar
12941309 }
12951310
12961311 // Return value is only `Some` if the level is `Error` or `DelayedBug`.
@@ -1334,7 +1349,7 @@ impl DiagCtxtInner {
13341349 DelayedBug => {
13351350 // If we have already emitted at least one error, we don't need
13361351 // 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 ( ) {
13381353 Some ( guar)
13391354 } else {
13401355 let backtrace = std:: backtrace:: Backtrace :: capture ( ) ;
@@ -1451,17 +1466,16 @@ impl DiagCtxtInner {
14511466 . is_some_and ( |c| self . err_guars . len ( ) + self . lint_err_guars . len ( ) + 1 >= c. get ( ) )
14521467 }
14531468
1454- fn has_errors ( & self ) -> Option < ErrorGuaranteed > {
1469+ fn has_errors_excluding_lint_errors ( & self ) -> Option < ErrorGuaranteed > {
14551470 self . err_guars . get ( 0 ) . copied ( )
14561471 }
14571472
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 ( ) )
14601475 }
14611476
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 ( ) )
14651479 }
14661480
14671481 /// Translate `message` eagerly with `args` to `SubdiagnosticMessage::Eager`.
@@ -1484,6 +1498,11 @@ impl DiagCtxtInner {
14841498 }
14851499
14861500 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+
14871506 if self . delayed_bugs . is_empty ( ) {
14881507 return ;
14891508 }
0 commit comments