4
4
5
5
#![ doc( html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/" ) ]
6
6
#![ feature( crate_visibility_modifier) ]
7
+ #![ feature( drain_filter) ]
7
8
#![ feature( backtrace) ]
8
9
#![ feature( if_let_guard) ]
9
10
#![ feature( let_else) ]
@@ -919,7 +920,7 @@ impl Handler {
919
920
self . inner . borrow_mut ( ) . force_print_diagnostic ( db)
920
921
}
921
922
922
- pub fn emit_diagnostic ( & self , diagnostic : & Diagnostic ) -> Option < ErrorGuaranteed > {
923
+ pub fn emit_diagnostic ( & self , diagnostic : & mut Diagnostic ) -> Option < ErrorGuaranteed > {
923
924
self . inner . borrow_mut ( ) . emit_diagnostic ( diagnostic)
924
925
}
925
926
@@ -993,25 +994,25 @@ impl HandlerInner {
993
994
self . taught_diagnostics . insert ( code. clone ( ) )
994
995
}
995
996
996
- fn force_print_diagnostic ( & mut self , db : Diagnostic ) {
997
- self . emitter . emit_diagnostic ( & db) ;
997
+ fn force_print_diagnostic ( & mut self , mut db : Diagnostic ) {
998
+ self . emitter . emit_diagnostic ( & mut db) ;
998
999
}
999
1000
1000
1001
/// Emit all stashed diagnostics.
1001
1002
fn emit_stashed_diagnostics ( & mut self ) -> Option < ErrorGuaranteed > {
1002
1003
let diags = self . stashed_diagnostics . drain ( ..) . map ( |x| x. 1 ) . collect :: < Vec < _ > > ( ) ;
1003
1004
let mut reported = None ;
1004
- diags . iter ( ) . for_each ( | diag| {
1005
+ for mut diag in diags {
1005
1006
if diag. is_error ( ) {
1006
1007
reported = Some ( ErrorGuaranteed ( ( ) ) ) ;
1007
1008
}
1008
- self . emit_diagnostic ( diag) ;
1009
- } ) ;
1009
+ self . emit_diagnostic ( & mut diag) ;
1010
+ }
1010
1011
reported
1011
1012
}
1012
1013
1013
1014
// FIXME(eddyb) this should ideally take `diagnostic` by value.
1014
- fn emit_diagnostic ( & mut self , diagnostic : & Diagnostic ) -> Option < ErrorGuaranteed > {
1015
+ fn emit_diagnostic ( & mut self , diagnostic : & mut Diagnostic ) -> Option < ErrorGuaranteed > {
1015
1016
if diagnostic. level == Level :: DelayedBug {
1016
1017
// FIXME(eddyb) this should check for `has_errors` and stop pushing
1017
1018
// once *any* errors were emitted (and truncate `delayed_span_bugs`
@@ -1070,7 +1071,23 @@ impl HandlerInner {
1070
1071
// Only emit the diagnostic if we've been asked to deduplicate and
1071
1072
// haven't already emitted an equivalent diagnostic.
1072
1073
if !( self . flags . deduplicate_diagnostics && already_emitted ( self ) ) {
1073
- self . emitter . emit_diagnostic ( diagnostic) ;
1074
+ debug ! ( ?diagnostic) ;
1075
+ debug ! ( ?self . emitted_diagnostics) ;
1076
+ let already_emitted_sub = |sub : & mut SubDiagnostic | {
1077
+ debug ! ( ?sub) ;
1078
+ if sub. level != Level :: OnceNote {
1079
+ return false ;
1080
+ }
1081
+ let mut hasher = StableHasher :: new ( ) ;
1082
+ sub. hash ( & mut hasher) ;
1083
+ let diagnostic_hash = hasher. finish ( ) ;
1084
+ debug ! ( ?diagnostic_hash) ;
1085
+ !self . emitted_diagnostics . insert ( diagnostic_hash)
1086
+ } ;
1087
+
1088
+ diagnostic. children . drain_filter ( already_emitted_sub) . for_each ( |_| { } ) ;
1089
+
1090
+ self . emitter . emit_diagnostic ( & diagnostic) ;
1074
1091
if diagnostic. is_error ( ) {
1075
1092
self . deduplicated_err_count += 1 ;
1076
1093
} else if diagnostic. level == Warning {
@@ -1221,22 +1238,22 @@ impl HandlerInner {
1221
1238
let mut diagnostic = Diagnostic :: new ( Level :: DelayedBug , msg) ;
1222
1239
diagnostic. set_span ( sp. into ( ) ) ;
1223
1240
diagnostic. note ( & format ! ( "delayed at {}" , std:: panic:: Location :: caller( ) ) ) ;
1224
- self . emit_diagnostic ( & diagnostic) . unwrap ( )
1241
+ self . emit_diagnostic ( & mut diagnostic) . unwrap ( )
1225
1242
}
1226
1243
1227
1244
// FIXME(eddyb) note the comment inside `impl Drop for HandlerInner`, that's
1228
1245
// where the explanation of what "good path" is (also, it should be renamed).
1229
1246
fn delay_good_path_bug ( & mut self , msg : & str ) {
1230
- let diagnostic = Diagnostic :: new ( Level :: DelayedBug , msg) ;
1247
+ let mut diagnostic = Diagnostic :: new ( Level :: DelayedBug , msg) ;
1231
1248
if self . flags . report_delayed_bugs {
1232
- self . emit_diagnostic ( & diagnostic) ;
1249
+ self . emit_diagnostic ( & mut diagnostic) ;
1233
1250
}
1234
1251
let backtrace = std:: backtrace:: Backtrace :: force_capture ( ) ;
1235
1252
self . delayed_good_path_bugs . push ( DelayedDiagnostic :: with_backtrace ( diagnostic, backtrace) ) ;
1236
1253
}
1237
1254
1238
1255
fn failure ( & mut self , msg : & str ) {
1239
- self . emit_diagnostic ( & Diagnostic :: new ( FailureNote , msg) ) ;
1256
+ self . emit_diagnostic ( & mut Diagnostic :: new ( FailureNote , msg) ) ;
1240
1257
}
1241
1258
1242
1259
fn fatal ( & mut self , msg : & str ) -> FatalError {
@@ -1253,11 +1270,11 @@ impl HandlerInner {
1253
1270
if self . treat_err_as_bug ( ) {
1254
1271
self . bug ( msg) ;
1255
1272
}
1256
- self . emit_diagnostic ( & Diagnostic :: new ( level, msg) ) . unwrap ( )
1273
+ self . emit_diagnostic ( & mut Diagnostic :: new ( level, msg) ) . unwrap ( )
1257
1274
}
1258
1275
1259
1276
fn bug ( & mut self , msg : & str ) -> ! {
1260
- self . emit_diagnostic ( & Diagnostic :: new ( Bug , msg) ) ;
1277
+ self . emit_diagnostic ( & mut Diagnostic :: new ( Bug , msg) ) ;
1261
1278
panic:: panic_any ( ExplicitBug ) ;
1262
1279
}
1263
1280
@@ -1267,7 +1284,7 @@ impl HandlerInner {
1267
1284
if no_bugs {
1268
1285
// Put the overall explanation before the `DelayedBug`s, to
1269
1286
// frame them better (e.g. separate warnings from them).
1270
- self . emit_diagnostic ( & Diagnostic :: new ( Bug , explanation) ) ;
1287
+ self . emit_diagnostic ( & mut Diagnostic :: new ( Bug , explanation) ) ;
1271
1288
no_bugs = false ;
1272
1289
}
1273
1290
@@ -1283,7 +1300,7 @@ impl HandlerInner {
1283
1300
}
1284
1301
bug. level = Level :: Bug ;
1285
1302
1286
- self . emit_diagnostic ( & bug) ;
1303
+ self . emit_diagnostic ( & mut bug) ;
1287
1304
}
1288
1305
1289
1306
// Panic with `ExplicitBug` to avoid "unexpected panic" messages.
@@ -1350,6 +1367,8 @@ pub enum Level {
1350
1367
} ,
1351
1368
Warning ,
1352
1369
Note ,
1370
+ /// A note that is only emitted once.
1371
+ OnceNote ,
1353
1372
Help ,
1354
1373
FailureNote ,
1355
1374
Allow ,
@@ -1372,7 +1391,7 @@ impl Level {
1372
1391
Warning => {
1373
1392
spec. set_fg ( Some ( Color :: Yellow ) ) . set_intense ( cfg ! ( windows) ) ;
1374
1393
}
1375
- Note => {
1394
+ Note | OnceNote => {
1376
1395
spec. set_fg ( Some ( Color :: Green ) ) . set_intense ( true ) ;
1377
1396
}
1378
1397
Help => {
@@ -1389,7 +1408,7 @@ impl Level {
1389
1408
Bug | DelayedBug => "error: internal compiler error" ,
1390
1409
Fatal | Error { .. } => "error" ,
1391
1410
Warning => "warning" ,
1392
- Note => "note" ,
1411
+ Note | OnceNote => "note" ,
1393
1412
Help => "help" ,
1394
1413
FailureNote => "failure-note" ,
1395
1414
Allow => panic ! ( "Shouldn't call on allowed error" ) ,
0 commit comments