@@ -28,11 +28,32 @@ use middle::def_id::DefId;
28
28
use middle:: infer:: InferCtxt ;
29
29
use middle:: ty:: { self , ToPredicate , HasTypeFlags , ToPolyTraitRef , TraitRef , Ty } ;
30
30
use middle:: ty:: fold:: TypeFoldable ;
31
- use std:: collections:: HashMap ;
31
+ use util:: nodemap:: { FnvHashMap , FnvHashSet } ;
32
+
32
33
use std:: fmt;
33
34
use syntax:: codemap:: Span ;
34
35
use rustc_front:: attr:: { AttributeMethods , AttrMetaMethods } ;
35
36
37
+ #[ derive( Debug , PartialEq , Eq , Hash ) ]
38
+ pub struct TraitErrorKey < ' tcx > {
39
+ is_warning : bool ,
40
+ span : Span ,
41
+ predicate : ty:: Predicate < ' tcx >
42
+ }
43
+
44
+ impl < ' tcx > TraitErrorKey < ' tcx > {
45
+ fn from_error < ' a > ( infcx : & InferCtxt < ' a , ' tcx > ,
46
+ e : & FulfillmentError < ' tcx > ) -> Self {
47
+ let predicate =
48
+ infcx. resolve_type_vars_if_possible ( & e. obligation . predicate ) ;
49
+ TraitErrorKey {
50
+ is_warning : is_warning ( & e. obligation ) ,
51
+ span : e. obligation . cause . span ,
52
+ predicate : infcx. tcx . erase_regions ( & predicate)
53
+ }
54
+ }
55
+ }
56
+
36
57
pub fn report_fulfillment_errors < ' a , ' tcx > ( infcx : & InferCtxt < ' a , ' tcx > ,
37
58
errors : & Vec < FulfillmentError < ' tcx > > ) {
38
59
for error in errors {
@@ -42,6 +63,13 @@ pub fn report_fulfillment_errors<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
42
63
43
64
fn report_fulfillment_error < ' a , ' tcx > ( infcx : & InferCtxt < ' a , ' tcx > ,
44
65
error : & FulfillmentError < ' tcx > ) {
66
+ let error_key = TraitErrorKey :: from_error ( infcx, error) ;
67
+ debug ! ( "report_fulfillment_errors({:?}) - key={:?}" ,
68
+ error, error_key) ;
69
+ if !infcx. reported_trait_errors . borrow_mut ( ) . insert ( error_key) {
70
+ debug ! ( "report_fulfillment_errors: skipping duplicate" ) ;
71
+ return ;
72
+ }
45
73
match error. code {
46
74
FulfillmentErrorCode :: CodeSelectionError ( ref e) => {
47
75
report_selection_error ( infcx, & error. obligation , e) ;
@@ -97,7 +125,7 @@ fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
97
125
( gen. name . as_str ( ) . to_string ( ) ,
98
126
trait_ref. substs . types . get ( param, i)
99
127
. to_string ( ) )
100
- } ) . collect :: < HashMap < String , String > > ( ) ;
128
+ } ) . collect :: < FnvHashMap < String , String > > ( ) ;
101
129
generic_map. insert ( "Self" . to_string ( ) ,
102
130
trait_ref. self_ty ( ) . to_string ( ) ) ;
103
131
let parser = Parser :: new ( & istring) ;
@@ -302,7 +330,11 @@ pub fn report_object_safety_error<'tcx>(tcx: &ty::ctxt<'tcx>,
302
330
"the trait `{}` cannot be made into an object" ,
303
331
tcx. item_path_str( trait_def_id) ) ;
304
332
333
+ let mut reported_violations = FnvHashSet ( ) ;
305
334
for violation in object_safety_violations ( tcx, trait_def_id) {
335
+ if !reported_violations. insert ( violation. clone ( ) ) {
336
+ continue ;
337
+ }
306
338
match violation {
307
339
ObjectSafetyViolation :: SizedSelf => {
308
340
tcx. sess . fileline_note (
0 commit comments