@@ -28,11 +28,32 @@ use middle::def_id::DefId;
2828use middle:: infer:: InferCtxt ;
2929use middle:: ty:: { self , ToPredicate , HasTypeFlags , ToPolyTraitRef , TraitRef , Ty } ;
3030use middle:: ty:: fold:: TypeFoldable ;
31- use std:: collections:: HashMap ;
31+ use util:: nodemap:: { FnvHashMap , FnvHashSet } ;
32+
3233use std:: fmt;
3334use syntax:: codemap:: Span ;
3435use rustc_front:: attr:: { AttributeMethods , AttrMetaMethods } ;
3536
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+
3657pub fn report_fulfillment_errors < ' a , ' tcx > ( infcx : & InferCtxt < ' a , ' tcx > ,
3758 errors : & Vec < FulfillmentError < ' tcx > > ) {
3859 for error in errors {
@@ -42,6 +63,13 @@ pub fn report_fulfillment_errors<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
4263
4364fn report_fulfillment_error < ' a , ' tcx > ( infcx : & InferCtxt < ' a , ' tcx > ,
4465 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+ }
4573 match error. code {
4674 FulfillmentErrorCode :: CodeSelectionError ( ref e) => {
4775 report_selection_error ( infcx, & error. obligation , e) ;
@@ -97,7 +125,7 @@ fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
97125 ( gen. name . as_str ( ) . to_string ( ) ,
98126 trait_ref. substs . types . get ( param, i)
99127 . to_string ( ) )
100- } ) . collect :: < HashMap < String , String > > ( ) ;
128+ } ) . collect :: < FnvHashMap < String , String > > ( ) ;
101129 generic_map. insert ( "Self" . to_string ( ) ,
102130 trait_ref. self_ty ( ) . to_string ( ) ) ;
103131 let parser = Parser :: new ( & istring) ;
@@ -302,7 +330,11 @@ pub fn report_object_safety_error<'tcx>(tcx: &ty::ctxt<'tcx>,
302330 "the trait `{}` cannot be made into an object" ,
303331 tcx. item_path_str( trait_def_id) ) ;
304332
333+ let mut reported_violations = FnvHashSet ( ) ;
305334 for violation in object_safety_violations ( tcx, trait_def_id) {
335+ if !reported_violations. insert ( violation. clone ( ) ) {
336+ continue ;
337+ }
306338 match violation {
307339 ObjectSafetyViolation :: SizedSelf => {
308340 tcx. sess . fileline_note (
0 commit comments