@@ -471,9 +471,10 @@ struct DiagCtxtInner {
471471 emitted_diagnostics : FxHashSet < Hash128 > ,
472472
473473 /// 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.
477478 stashed_diagnostics : FxIndexMap < ( Span , StashKey ) , Diagnostic > ,
478479
479480 future_breakage_diagnostics : Vec < Diagnostic > ,
@@ -558,7 +559,9 @@ pub struct DiagCtxtFlags {
558559
559560impl Drop for DiagCtxtInner {
560561 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( ) ) ;
562565
563566 if self . err_guars . is_empty ( ) {
564567 self . flush_delayed ( )
@@ -750,17 +753,24 @@ impl DiagCtxt {
750753 }
751754
752755 /// Emit all stashed diagnostics.
753- pub fn emit_stashed_diagnostics ( & self ) {
756+ pub fn emit_stashed_diagnostics ( & self ) -> Option < ErrorGuaranteed > {
754757 self . inner . borrow_mut ( ) . emit_stashed_diagnostics ( )
755758 }
756759
757- /// This excludes lint errors, delayed bugs, and stashed errors.
760+ /// This excludes lint errors, delayed bugs and stashed errors.
758761 #[ inline]
759- pub fn err_count ( & self ) -> usize {
762+ pub fn err_count_excluding_lint_errs ( & self ) -> usize {
760763 self . inner . borrow ( ) . err_guars . len ( )
761764 }
762765
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
764774 /// absolutely necessary, avoid using this. It's dubious because stashed
765775 /// errors can later be cancelled, so the presence of a stashed error at
766776 /// some point of time doesn't guarantee anything -- there are no
@@ -769,27 +779,29 @@ impl DiagCtxt {
769779 self . inner . borrow ( ) . stashed_err_count
770780 }
771781
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 ( )
775786 }
776787
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 ( )
781791 }
782792
783793 /// 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 ( )
787797 }
788798
789799 pub fn print_error_count ( & self , registry : & Registry ) {
790800 let mut inner = self . inner . borrow_mut ( ) ;
791801
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( ) ) ;
793805
794806 if inner. treat_err_as_bug ( ) {
795807 return ;
@@ -864,10 +876,12 @@ impl DiagCtxt {
864876 }
865877 }
866878
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.
867883 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 ( ) {
871885 FatalError . raise ( ) ;
872886 }
873887 }
@@ -1268,10 +1282,10 @@ impl DiagCtxt {
12681282// `DiagCtxtInner::foo`.
12691283impl DiagCtxtInner {
12701284 /// 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 ;
12721287 let has_errors = !self . err_guars . is_empty ( ) ;
12731288 for ( _, diag) in std:: mem:: take ( & mut self . stashed_diagnostics ) . into_iter ( ) {
1274- // Decrement the count tracking the stash; emitting will increment it.
12751289 if diag. is_error ( ) {
12761290 if diag. is_lint . is_none ( ) {
12771291 self . stashed_err_count -= 1 ;
@@ -1284,8 +1298,9 @@ impl DiagCtxtInner {
12841298 continue ;
12851299 }
12861300 }
1287- self . emit_diagnostic ( diag) ;
1301+ guar = guar . or ( self . emit_diagnostic ( diag) ) ;
12881302 }
1303+ guar
12891304 }
12901305
12911306 // Return value is only `Some` if the level is `Error` or `DelayedBug`.
@@ -1329,7 +1344,7 @@ impl DiagCtxtInner {
13291344 DelayedBug => {
13301345 // If we have already emitted at least one error, we don't need
13311346 // 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 ( ) {
13331348 Some ( guar)
13341349 } else {
13351350 let backtrace = std:: backtrace:: Backtrace :: capture ( ) ;
@@ -1445,17 +1460,16 @@ impl DiagCtxtInner {
14451460 . is_some_and ( |c| self . err_guars . len ( ) + self . lint_err_guars . len ( ) + 1 >= c. get ( ) )
14461461 }
14471462
1448- fn has_errors ( & self ) -> Option < ErrorGuaranteed > {
1463+ fn has_errors_excluding_lint_errors ( & self ) -> Option < ErrorGuaranteed > {
14491464 self . err_guars . get ( 0 ) . copied ( )
14501465 }
14511466
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 ( ) )
14541469 }
14551470
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 ( ) )
14591473 }
14601474
14611475 /// Translate `message` eagerly with `args` to `SubdiagnosticMessage::Eager`.
@@ -1488,6 +1502,11 @@ impl DiagCtxtInner {
14881502 }
14891503
14901504 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+
14911510 if self . delayed_bugs . is_empty ( ) {
14921511 return ;
14931512 }
0 commit comments