18
18
#![ feature( range_contains) ]
19
19
#![ cfg_attr( unix, feature( libc) ) ]
20
20
#![ feature( conservative_impl_trait) ]
21
+ #![ feature( i128_type) ]
21
22
22
23
extern crate term;
23
24
#[ cfg( unix) ]
24
25
extern crate libc;
26
+ extern crate rustc_data_structures;
25
27
extern crate serialize as rustc_serialize;
26
28
extern crate syntax_pos;
27
29
@@ -31,6 +33,9 @@ use self::Level::*;
31
33
32
34
use emitter:: { Emitter , EmitterWriter } ;
33
35
36
+ use rustc_data_structures:: fx:: FxHashSet ;
37
+ use rustc_data_structures:: stable_hasher:: StableHasher ;
38
+
34
39
use std:: borrow:: Cow ;
35
40
use std:: cell:: { RefCell , Cell } ;
36
41
use std:: mem;
@@ -47,7 +52,7 @@ mod lock;
47
52
48
53
use syntax_pos:: { BytePos , Loc , FileLinesResult , FileMap , FileName , MultiSpan , Span , NO_EXPANSION } ;
49
54
50
- #[ derive( Clone , Debug , PartialEq , RustcEncodable , RustcDecodable ) ]
55
+ #[ derive( Clone , Debug , PartialEq , Hash , RustcEncodable , RustcDecodable ) ]
51
56
pub enum RenderSpan {
52
57
/// A FullSpan renders with both with an initial line for the
53
58
/// message, prefixed by file:linenum, followed by a summary of
@@ -61,7 +66,7 @@ pub enum RenderSpan {
61
66
Suggestion ( CodeSuggestion ) ,
62
67
}
63
68
64
- #[ derive( Clone , Debug , PartialEq , RustcEncodable , RustcDecodable ) ]
69
+ #[ derive( Clone , Debug , PartialEq , Hash , RustcEncodable , RustcDecodable ) ]
65
70
pub struct CodeSuggestion {
66
71
/// Each substitute can have multiple variants due to multiple
67
72
/// applicable suggestions
@@ -86,7 +91,7 @@ pub struct CodeSuggestion {
86
91
pub show_code_when_inline : bool ,
87
92
}
88
93
89
- #[ derive( Clone , Debug , PartialEq , RustcEncodable , RustcDecodable ) ]
94
+ #[ derive( Clone , Debug , PartialEq , Hash , RustcEncodable , RustcDecodable ) ]
90
95
/// See the docs on `CodeSuggestion::substitutions`
91
96
pub struct Substitution {
92
97
pub span : Span ,
@@ -271,6 +276,11 @@ pub struct Handler {
271
276
continue_after_error : Cell < bool > ,
272
277
delayed_span_bug : RefCell < Option < Diagnostic > > ,
273
278
tracked_diagnostics : RefCell < Option < Vec < Diagnostic > > > ,
279
+
280
+ // This set contains a hash of every diagnostic that has been emitted by
281
+ // this handler. These hashes is used to avoid emitting the same error
282
+ // twice.
283
+ emitted_diagnostics : RefCell < FxHashSet < u128 > > ,
274
284
}
275
285
276
286
impl Handler {
@@ -295,6 +305,7 @@ impl Handler {
295
305
continue_after_error : Cell :: new ( true ) ,
296
306
delayed_span_bug : RefCell :: new ( None ) ,
297
307
tracked_diagnostics : RefCell :: new ( None ) ,
308
+ emitted_diagnostics : RefCell :: new ( FxHashSet ( ) ) ,
298
309
}
299
310
}
300
311
@@ -559,15 +570,29 @@ impl Handler {
559
570
}
560
571
561
572
fn emit_db ( & self , db : & DiagnosticBuilder ) {
573
+ let diagnostic = & * * db;
574
+
562
575
if let Some ( ref mut list) = * self . tracked_diagnostics . borrow_mut ( ) {
563
- list. push ( ( * * db) . clone ( ) ) ;
576
+ list. push ( diagnostic. clone ( ) ) ;
577
+ }
578
+
579
+ let diagnostic_hash = {
580
+ use std:: hash:: Hash ;
581
+ let mut hasher = StableHasher :: new ( ) ;
582
+ diagnostic. hash ( & mut hasher) ;
583
+ hasher. finish ( )
584
+ } ;
585
+
586
+ // Only emit the diagnostic if we haven't already emitted an equivalent
587
+ // one:
588
+ if self . emitted_diagnostics . borrow_mut ( ) . insert ( diagnostic_hash) {
589
+ self . emitter . borrow_mut ( ) . emit ( db) ;
564
590
}
565
- self . emitter . borrow_mut ( ) . emit ( db) ;
566
591
}
567
592
}
568
593
569
594
570
- #[ derive( Copy , PartialEq , Clone , Debug , RustcEncodable , RustcDecodable ) ]
595
+ #[ derive( Copy , PartialEq , Clone , Hash , Debug , RustcEncodable , RustcDecodable ) ]
571
596
pub enum Level {
572
597
Bug ,
573
598
Fatal ,
0 commit comments