@@ -491,10 +491,15 @@ impl Drop for HandlerInner {
491
491
self . flush_delayed ( bugs, "no errors encountered even though `delay_span_bug` issued" ) ;
492
492
}
493
493
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.
494
499
if !self . has_any_message ( ) {
495
500
let bugs = std:: mem:: replace ( & mut self . delayed_good_path_bugs , Vec :: new ( ) ) ;
496
501
self . flush_delayed (
497
- bugs. into_iter ( ) . map ( DelayedDiagnostic :: decorate) . collect ( ) ,
502
+ bugs. into_iter ( ) . map ( DelayedDiagnostic :: decorate) ,
498
503
"no warnings or errors encountered even though `delayed_good_path_bugs` issued" ,
499
504
) ;
500
505
}
@@ -815,6 +820,8 @@ impl Handler {
815
820
self . inner . borrow_mut ( ) . delay_span_bug ( span, msg)
816
821
}
817
822
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).
818
825
pub fn delay_good_path_bug ( & self , msg : & str ) {
819
826
self . inner . borrow_mut ( ) . delay_good_path_bug ( msg)
820
827
}
@@ -915,10 +922,6 @@ impl Handler {
915
922
pub fn emit_unused_externs ( & self , lint_level : & str , unused_externs : & [ & str ] ) {
916
923
self . inner . borrow_mut ( ) . emit_unused_externs ( lint_level, unused_externs)
917
924
}
918
-
919
- pub fn delay_as_bug ( & self , diagnostic : Diagnostic ) {
920
- self . inner . borrow_mut ( ) . delay_as_bug ( diagnostic)
921
- }
922
925
}
923
926
924
927
impl HandlerInner {
@@ -936,11 +939,24 @@ impl HandlerInner {
936
939
diags. iter ( ) . for_each ( |diag| self . emit_diagnostic ( diag) ) ;
937
940
}
938
941
942
+ // FIXME(eddyb) this should ideally take `diagnostic` by value.
939
943
fn emit_diagnostic ( & mut self , diagnostic : & Diagnostic ) {
940
944
if diagnostic. cancelled ( ) {
941
945
return ;
942
946
}
943
947
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
+
944
960
if diagnostic. has_future_breakage ( ) {
945
961
self . future_breakage_diagnostics . push ( diagnostic. clone ( ) ) ;
946
962
}
@@ -1119,14 +1135,16 @@ impl HandlerInner {
1119
1135
// FIXME: don't abort here if report_delayed_bugs is off
1120
1136
self . span_bug ( sp, msg) ;
1121
1137
}
1122
- let mut diagnostic = Diagnostic :: new ( Level :: Bug , msg) ;
1138
+ let mut diagnostic = Diagnostic :: new ( Level :: DelayedBug , msg) ;
1123
1139
diagnostic. set_span ( sp. into ( ) ) ;
1124
1140
diagnostic. note ( & format ! ( "delayed at {}" , std:: panic:: Location :: caller( ) ) ) ;
1125
- self . delay_as_bug ( diagnostic)
1141
+ self . emit_diagnostic ( & diagnostic)
1126
1142
}
1127
1143
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).
1128
1146
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) ;
1130
1148
if self . flags . report_delayed_bugs {
1131
1149
self . emit_diagnostic ( & diagnostic) ;
1132
1150
}
@@ -1160,20 +1178,34 @@ impl HandlerInner {
1160
1178
panic:: panic_any ( ExplicitBug ) ;
1161
1179
}
1162
1180
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 ;
1169
1202
1170
- fn flush_delayed ( & mut self , bugs : Vec < Diagnostic > , explanation : & str ) {
1171
- let has_bugs = !bugs. is_empty ( ) ;
1172
- for bug in bugs {
1173
1203
self . emit_diagnostic ( & bug) ;
1174
1204
}
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 ) ;
1177
1209
}
1178
1210
}
1179
1211
@@ -1227,6 +1259,7 @@ impl DelayedDiagnostic {
1227
1259
#[ derive( Copy , PartialEq , Clone , Hash , Debug , Encodable , Decodable ) ]
1228
1260
pub enum Level {
1229
1261
Bug ,
1262
+ DelayedBug ,
1230
1263
Fatal ,
1231
1264
Error {
1232
1265
/// If this error comes from a lint, don't abort compilation even when abort_if_errors() is called.
@@ -1250,7 +1283,7 @@ impl Level {
1250
1283
fn color ( self ) -> ColorSpec {
1251
1284
let mut spec = ColorSpec :: new ( ) ;
1252
1285
match self {
1253
- Bug | Fatal | Error { .. } => {
1286
+ Bug | DelayedBug | Fatal | Error { .. } => {
1254
1287
spec. set_fg ( Some ( Color :: Red ) ) . set_intense ( true ) ;
1255
1288
}
1256
1289
Warning => {
@@ -1270,7 +1303,7 @@ impl Level {
1270
1303
1271
1304
pub fn to_str ( self ) -> & ' static str {
1272
1305
match self {
1273
- Bug => "error: internal compiler error" ,
1306
+ Bug | DelayedBug => "error: internal compiler error" ,
1274
1307
Fatal | Error { .. } => "error" ,
1275
1308
Warning => "warning" ,
1276
1309
Note => "note" ,
0 commit comments