44
55#![ doc( html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/" ) ]
66#![ feature( crate_visibility_modifier) ]
7+ #![ feature( drain_filter) ]
78#![ feature( backtrace) ]
89#![ feature( if_let_guard) ]
910#![ feature( let_else) ]
@@ -919,7 +920,7 @@ impl Handler {
919920 self . inner . borrow_mut ( ) . force_print_diagnostic ( db)
920921 }
921922
922- pub fn emit_diagnostic ( & self , diagnostic : & Diagnostic ) -> Option < ErrorGuaranteed > {
923+ pub fn emit_diagnostic ( & self , diagnostic : & mut Diagnostic ) -> Option < ErrorGuaranteed > {
923924 self . inner . borrow_mut ( ) . emit_diagnostic ( diagnostic)
924925 }
925926
@@ -993,25 +994,25 @@ impl HandlerInner {
993994 self . taught_diagnostics . insert ( code. clone ( ) )
994995 }
995996
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) ;
998999 }
9991000
10001001 /// Emit all stashed diagnostics.
10011002 fn emit_stashed_diagnostics ( & mut self ) -> Option < ErrorGuaranteed > {
10021003 let diags = self . stashed_diagnostics . drain ( ..) . map ( |x| x. 1 ) . collect :: < Vec < _ > > ( ) ;
10031004 let mut reported = None ;
1004- diags . iter ( ) . for_each ( | diag| {
1005+ for mut diag in diags {
10051006 if diag. is_error ( ) {
10061007 reported = Some ( ErrorGuaranteed ( ( ) ) ) ;
10071008 }
1008- self . emit_diagnostic ( diag) ;
1009- } ) ;
1009+ self . emit_diagnostic ( & mut diag) ;
1010+ }
10101011 reported
10111012 }
10121013
10131014 // 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 > {
10151016 if diagnostic. level == Level :: DelayedBug {
10161017 // FIXME(eddyb) this should check for `has_errors` and stop pushing
10171018 // once *any* errors were emitted (and truncate `delayed_span_bugs`
@@ -1070,7 +1071,23 @@ impl HandlerInner {
10701071 // Only emit the diagnostic if we've been asked to deduplicate and
10711072 // haven't already emitted an equivalent diagnostic.
10721073 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) ;
10741091 if diagnostic. is_error ( ) {
10751092 self . deduplicated_err_count += 1 ;
10761093 } else if diagnostic. level == Warning {
@@ -1221,22 +1238,22 @@ impl HandlerInner {
12211238 let mut diagnostic = Diagnostic :: new ( Level :: DelayedBug , msg) ;
12221239 diagnostic. set_span ( sp. into ( ) ) ;
12231240 diagnostic. note ( & format ! ( "delayed at {}" , std:: panic:: Location :: caller( ) ) ) ;
1224- self . emit_diagnostic ( & diagnostic) . unwrap ( )
1241+ self . emit_diagnostic ( & mut diagnostic) . unwrap ( )
12251242 }
12261243
12271244 // FIXME(eddyb) note the comment inside `impl Drop for HandlerInner`, that's
12281245 // where the explanation of what "good path" is (also, it should be renamed).
12291246 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) ;
12311248 if self . flags . report_delayed_bugs {
1232- self . emit_diagnostic ( & diagnostic) ;
1249+ self . emit_diagnostic ( & mut diagnostic) ;
12331250 }
12341251 let backtrace = std:: backtrace:: Backtrace :: force_capture ( ) ;
12351252 self . delayed_good_path_bugs . push ( DelayedDiagnostic :: with_backtrace ( diagnostic, backtrace) ) ;
12361253 }
12371254
12381255 fn failure ( & mut self , msg : & str ) {
1239- self . emit_diagnostic ( & Diagnostic :: new ( FailureNote , msg) ) ;
1256+ self . emit_diagnostic ( & mut Diagnostic :: new ( FailureNote , msg) ) ;
12401257 }
12411258
12421259 fn fatal ( & mut self , msg : & str ) -> FatalError {
@@ -1253,11 +1270,11 @@ impl HandlerInner {
12531270 if self . treat_err_as_bug ( ) {
12541271 self . bug ( msg) ;
12551272 }
1256- self . emit_diagnostic ( & Diagnostic :: new ( level, msg) ) . unwrap ( )
1273+ self . emit_diagnostic ( & mut Diagnostic :: new ( level, msg) ) . unwrap ( )
12571274 }
12581275
12591276 fn bug ( & mut self , msg : & str ) -> ! {
1260- self . emit_diagnostic ( & Diagnostic :: new ( Bug , msg) ) ;
1277+ self . emit_diagnostic ( & mut Diagnostic :: new ( Bug , msg) ) ;
12611278 panic:: panic_any ( ExplicitBug ) ;
12621279 }
12631280
@@ -1267,7 +1284,7 @@ impl HandlerInner {
12671284 if no_bugs {
12681285 // Put the overall explanation before the `DelayedBug`s, to
12691286 // 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) ) ;
12711288 no_bugs = false ;
12721289 }
12731290
@@ -1283,7 +1300,7 @@ impl HandlerInner {
12831300 }
12841301 bug. level = Level :: Bug ;
12851302
1286- self . emit_diagnostic ( & bug) ;
1303+ self . emit_diagnostic ( & mut bug) ;
12871304 }
12881305
12891306 // Panic with `ExplicitBug` to avoid "unexpected panic" messages.
@@ -1350,6 +1367,8 @@ pub enum Level {
13501367 } ,
13511368 Warning ,
13521369 Note ,
1370+ /// A note that is only emitted once.
1371+ OnceNote ,
13531372 Help ,
13541373 FailureNote ,
13551374 Allow ,
@@ -1372,7 +1391,7 @@ impl Level {
13721391 Warning => {
13731392 spec. set_fg ( Some ( Color :: Yellow ) ) . set_intense ( cfg ! ( windows) ) ;
13741393 }
1375- Note => {
1394+ Note | OnceNote => {
13761395 spec. set_fg ( Some ( Color :: Green ) ) . set_intense ( true ) ;
13771396 }
13781397 Help => {
@@ -1389,7 +1408,7 @@ impl Level {
13891408 Bug | DelayedBug => "error: internal compiler error" ,
13901409 Fatal | Error { .. } => "error" ,
13911410 Warning => "warning" ,
1392- Note => "note" ,
1411+ Note | OnceNote => "note" ,
13931412 Help => "help" ,
13941413 FailureNote => "failure-note" ,
13951414 Allow => panic ! ( "Shouldn't call on allowed error" ) ,
0 commit comments