@@ -491,10 +491,15 @@ impl Drop for HandlerInner {
491491 self . flush_delayed ( bugs, "no errors encountered even though `delay_span_bug` issued" ) ;
492492 }
493493
494+ // FIXME(eddyb) this explains what `delayed_good_path_bugs` are!
495+ // They're `delayed_span_bugs` but for "require some diagnostic happened"
496+ // instead of "require some error happened". Sadly that isn't ideal, as
497+ // lints can be `#[allow]`'d, potentially leading to this triggering.
498+ // Also, "good path" should be replaced with a better naming.
494499 if !self . has_any_message ( ) {
495500 let bugs = std:: mem:: replace ( & mut self . delayed_good_path_bugs , Vec :: new ( ) ) ;
496501 self . flush_delayed (
497- bugs. into_iter ( ) . map ( DelayedDiagnostic :: decorate) . collect ( ) ,
502+ bugs. into_iter ( ) . map ( DelayedDiagnostic :: decorate) ,
498503 "no warnings or errors encountered even though `delayed_good_path_bugs` issued" ,
499504 ) ;
500505 }
@@ -815,6 +820,8 @@ impl Handler {
815820 self . inner . borrow_mut ( ) . delay_span_bug ( span, msg)
816821 }
817822
823+ // FIXME(eddyb) note the comment inside `impl Drop for HandlerInner`, that's
824+ // where the explanation of what "good path" is (also, it should be renamed).
818825 pub fn delay_good_path_bug ( & self , msg : & str ) {
819826 self . inner . borrow_mut ( ) . delay_good_path_bug ( msg)
820827 }
@@ -915,10 +922,6 @@ impl Handler {
915922 pub fn emit_unused_externs ( & self , lint_level : & str , unused_externs : & [ & str ] ) {
916923 self . inner . borrow_mut ( ) . emit_unused_externs ( lint_level, unused_externs)
917924 }
918-
919- pub fn delay_as_bug ( & self , diagnostic : Diagnostic ) {
920- self . inner . borrow_mut ( ) . delay_as_bug ( diagnostic)
921- }
922925}
923926
924927impl HandlerInner {
@@ -936,11 +939,24 @@ impl HandlerInner {
936939 diags. iter ( ) . for_each ( |diag| self . emit_diagnostic ( diag) ) ;
937940 }
938941
942+ // FIXME(eddyb) this should ideally take `diagnostic` by value.
939943 fn emit_diagnostic ( & mut self , diagnostic : & Diagnostic ) {
940944 if diagnostic. cancelled ( ) {
941945 return ;
942946 }
943947
948+ if diagnostic. level == Level :: DelayedBug {
949+ // FIXME(eddyb) this should check for `has_errors` and stop pushing
950+ // once *any* errors were emitted (and truncate `delayed_span_bugs`
951+ // when an error is first emitted, also), but maybe there's a case
952+ // in which that's not sound? otherwise this is really inefficient.
953+ self . delayed_span_bugs . push ( diagnostic. clone ( ) ) ;
954+
955+ if !self . flags . report_delayed_bugs {
956+ return ;
957+ }
958+ }
959+
944960 if diagnostic. has_future_breakage ( ) {
945961 self . future_breakage_diagnostics . push ( diagnostic. clone ( ) ) ;
946962 }
@@ -1119,14 +1135,16 @@ impl HandlerInner {
11191135 // FIXME: don't abort here if report_delayed_bugs is off
11201136 self . span_bug ( sp, msg) ;
11211137 }
1122- let mut diagnostic = Diagnostic :: new ( Level :: Bug , msg) ;
1138+ let mut diagnostic = Diagnostic :: new ( Level :: DelayedBug , msg) ;
11231139 diagnostic. set_span ( sp. into ( ) ) ;
11241140 diagnostic. note ( & format ! ( "delayed at {}" , std:: panic:: Location :: caller( ) ) ) ;
1125- self . delay_as_bug ( diagnostic)
1141+ self . emit_diagnostic ( & diagnostic)
11261142 }
11271143
1144+ // FIXME(eddyb) note the comment inside `impl Drop for HandlerInner`, that's
1145+ // where the explanation of what "good path" is (also, it should be renamed).
11281146 fn delay_good_path_bug ( & mut self , msg : & str ) {
1129- let diagnostic = Diagnostic :: new ( Level :: Bug , msg) ;
1147+ let diagnostic = Diagnostic :: new ( Level :: DelayedBug , msg) ;
11301148 if self . flags . report_delayed_bugs {
11311149 self . emit_diagnostic ( & diagnostic) ;
11321150 }
@@ -1160,20 +1178,34 @@ impl HandlerInner {
11601178 panic:: panic_any ( ExplicitBug ) ;
11611179 }
11621180
1163- fn delay_as_bug ( & mut self , diagnostic : Diagnostic ) {
1164- if self . flags . report_delayed_bugs {
1165- self . emit_diagnostic ( & diagnostic) ;
1166- }
1167- self . delayed_span_bugs . push ( diagnostic) ;
1168- }
1181+ fn flush_delayed ( & mut self , bugs : impl IntoIterator < Item = Diagnostic > , explanation : & str ) {
1182+ let mut no_bugs = true ;
1183+ for mut bug in bugs {
1184+ if no_bugs {
1185+ // Put the overall explanation before the `DelayedBug`s, to
1186+ // frame them better (e.g. separate warnings from them).
1187+ self . emit_diagnostic ( & Diagnostic :: new ( Bug , explanation) ) ;
1188+ no_bugs = false ;
1189+ }
1190+
1191+ // "Undelay" the `DelayedBug`s (into plain `Bug`s).
1192+ if bug. level != Level :: DelayedBug {
1193+ // NOTE(eddyb) not panicking here because we're already producing
1194+ // an ICE, and the more information the merrier.
1195+ bug. note ( & format ! (
1196+ "`flushed_delayed` got diagnostic with level {:?}, \
1197+ instead of the expected `DelayedBug`",
1198+ bug. level,
1199+ ) ) ;
1200+ }
1201+ bug. level = Level :: Bug ;
11691202
1170- fn flush_delayed ( & mut self , bugs : Vec < Diagnostic > , explanation : & str ) {
1171- let has_bugs = !bugs. is_empty ( ) ;
1172- for bug in bugs {
11731203 self . emit_diagnostic ( & bug) ;
11741204 }
1175- if has_bugs {
1176- panic ! ( "{}" , explanation) ;
1205+
1206+ // Panic with `ExplicitBug` to avoid "unexpected panic" messages.
1207+ if !no_bugs {
1208+ panic:: panic_any ( ExplicitBug ) ;
11771209 }
11781210 }
11791211
@@ -1227,6 +1259,7 @@ impl DelayedDiagnostic {
12271259#[ derive( Copy , PartialEq , Clone , Hash , Debug , Encodable , Decodable ) ]
12281260pub enum Level {
12291261 Bug ,
1262+ DelayedBug ,
12301263 Fatal ,
12311264 Error {
12321265 /// If this error comes from a lint, don't abort compilation even when abort_if_errors() is called.
@@ -1250,7 +1283,7 @@ impl Level {
12501283 fn color ( self ) -> ColorSpec {
12511284 let mut spec = ColorSpec :: new ( ) ;
12521285 match self {
1253- Bug | Fatal | Error { .. } => {
1286+ Bug | DelayedBug | Fatal | Error { .. } => {
12541287 spec. set_fg ( Some ( Color :: Red ) ) . set_intense ( true ) ;
12551288 }
12561289 Warning => {
@@ -1270,7 +1303,7 @@ impl Level {
12701303
12711304 pub fn to_str ( self ) -> & ' static str {
12721305 match self {
1273- Bug => "error: internal compiler error" ,
1306+ Bug | DelayedBug => "error: internal compiler error" ,
12741307 Fatal | Error { .. } => "error" ,
12751308 Warning => "warning" ,
12761309 Note => "note" ,
0 commit comments