@@ -29,8 +29,8 @@ use hir::def_id::DefId;
2929use infer:: { self , InferCtxt , TypeOrigin } ;
3030use ty:: { self , ToPredicate , ToPolyTraitRef , TraitRef , Ty , TyCtxt , TypeFoldable } ;
3131use ty:: fast_reject;
32- use ty:: fold:: { TypeFoldable , TypeFolder } ;
33- use ty:: :: subst:: { self , Subst } ;
32+ use ty:: fold:: TypeFolder ;
33+ use ty:: subst:: { self , Subst } ;
3434use util:: nodemap:: { FnvHashMap , FnvHashSet } ;
3535
3636use std:: cmp;
@@ -62,7 +62,7 @@ impl<'a, 'gcx, 'tcx> TraitErrorKey<'tcx> {
6262 }
6363}
6464
65- fn impl_self_ty < ' a , ' tcx > ( fcx : & InferCtxt < ' a , ' tcx > ,
65+ fn impl_substs < ' a , ' tcx > ( fcx : & InferCtxt < ' a , ' tcx > ,
6666 did : DefId ,
6767 obligation : PredicateObligation < ' tcx > )
6868 -> subst:: Substs < ' tcx > {
@@ -82,35 +82,74 @@ fn impl_self_ty<'a, 'tcx>(fcx: &InferCtxt<'a, 'tcx>,
8282 substs
8383}
8484
85+ /*fn check_type_parameters<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
86+ trait_substs: &subst::Substs<'tcx>,
87+ impl_substs: &subst::Substs<'tcx>,
88+ obligation: &PredicateObligation<'tcx>) -> bool {
89+ let trait_types = trait_substs.types.as_slice();
90+ let impl_types = impl_substs.types.as_slice();
91+
92+ let mut failed = 0;
93+ for index_to_ignore in 0..trait_types.len() {
94+ for (index, (trait_type, impl_type)) in trait_types.iter()
95+ .zip(impl_types.iter())
96+ .enumerate() {
97+ if index_to_ignore != index &&
98+ infer::mk_eqty(infcx, true,
99+ TypeOrigin::Misc(obligation.cause.span),
100+ trait_type,
101+ impl_type).is_err() {
102+ failed += 1;
103+ break;
104+ }
105+ }
106+ }
107+ failed == trait_types.len() - 1
108+ }*/
109+
85110fn get_current_failing_impl < ' a , ' tcx > ( infcx : & InferCtxt < ' a , ' tcx > ,
86111 trait_ref : & TraitRef < ' tcx > ,
87112 obligation : & PredicateObligation < ' tcx > )
88- -> Option < DefId > {
113+ -> Option < ( DefId , subst:: Substs < ' tcx > ) > {
114+ println ! ( "1" ) ;
89115 let simp = fast_reject:: simplify_type ( infcx. tcx ,
90116 trait_ref. self_ty ( ) ,
91117 true ) ;
92118 let trait_def = infcx. tcx . lookup_trait_def ( trait_ref. def_id ) ;
93119
94120 match simp {
95121 Some ( _) => {
96- let mut ret = None ;
122+ println ! ( "2" ) ;
123+ let mut matching_impls = Vec :: new ( ) ;
97124 trait_def. for_each_impl ( infcx. tcx , |def_id| {
98125 let imp = infcx. tcx . impl_trait_ref ( def_id) . unwrap ( ) ;
99- let imp = imp. subst ( infcx. tcx , & impl_self_ty ( infcx, def_id, obligation. clone ( ) ) ) ;
100- if ret. is_none ( ) {
101- for error in infcx. reported_trait_errors . borrow ( ) . iter ( ) {
102- if let ty:: Predicate :: Trait ( ref t) = error. predicate {
103- if infer:: mk_eqty ( infcx, true , TypeOrigin :: Misc ( obligation. cause . span ) ,
104- t. skip_binder ( ) . trait_ref . self_ty ( ) ,
105- imp. self_ty ( ) ) . is_ok ( ) {
106- ret = Some ( def_id) ;
107- break ;
108- }
109- }
110- }
126+ let substs = impl_substs ( infcx, def_id, obligation. clone ( ) ) ;
127+ let imp = imp. subst ( infcx. tcx , & substs) ;
128+
129+ if infer:: mk_eqty ( infcx, true ,
130+ TypeOrigin :: Misc ( obligation. cause . span ) ,
131+ trait_ref. self_ty ( ) ,
132+ imp. self_ty ( ) ) . is_ok ( ) {
133+ //if check_type_parameters(infcx, &trait_ref.substs, &imp.substs, obligation) {
134+ matching_impls. push ( ( def_id, imp. substs . clone ( ) ) ) ;
135+ //}
111136 }
137+ println ! ( "=> {:?} /// {:?}" , def_id, imp. substs) ;
112138 } ) ;
113- ret
139+ if matching_impls. len ( ) == 0 {
140+ println ! ( "3" ) ;
141+ None
142+ } else if matching_impls. len ( ) == 1 {
143+ println ! ( "4" ) ;
144+ Some ( matching_impls[ 0 ] . clone ( ) )
145+ } else {
146+ println ! ( "5" ) ;
147+ // we need to determine which type is the good one!
148+ for & ( ref m, ref n) in matching_impls. iter ( ) {
149+ println ! ( "=> {:?} /// {:?}" , m, n) ;
150+ }
151+ Some ( matching_impls[ 0 ] . clone ( ) )
152+ }
114153 } ,
115154 None => None ,
116155 }
@@ -128,19 +167,21 @@ fn find_attr<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
128167 None
129168}
130169
131- fn report_on_unimplemented < ' a , ' tcx > ( infcx : & InferCtxt < ' a , ' tcx > ,
132- trait_ref : & TraitRef < ' tcx > ,
133- obligation : & PredicateObligation < ' tcx > )
134- -> Option < String > {
170+ fn on_unimplemented_note < ' a , ' tcx > ( infcx : & InferCtxt < ' a , ' tcx > ,
171+ trait_ref : ty:: PolyTraitRef < ' tcx > ,
172+ obligation : & PredicateObligation < ' tcx > ) -> Option < String > {
173+ let trait_ref = trait_ref. skip_binder ( ) ;
174+ //let def_id = trait_ref.def_id;
175+ let mut report = None ;
135176 let def_id = match get_current_failing_impl ( infcx, trait_ref, obligation) {
136- Some ( def_id) => {
177+ Some ( ( def_id, _ ) ) => {
137178 if let Some ( _) = find_attr ( infcx, def_id, "rustc_on_unimplemented" ) {
138179 def_id
139180 } else {
140181 trait_ref. def_id
141182 }
142183 } ,
143- None => trait_ref. def_id ,
184+ None => trait_ref. def_id ,
144185 } ;
145186 let span = obligation. cause . span ;
146187 let mut report = None ;
@@ -572,11 +613,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
572613 // "the type `T` can't be frobnicated"
573614 // which is somewhat confusing.
574615 err. help ( & format ! ( "consider adding a `where {}` bound" ,
575- trait_ref. to_predicate( ) ) ) ;
616+ trait_ref. to_predicate( ) ) ) ;
576617 } else if let Some ( s) = on_unimplemented_note ( infcx, trait_ref,
577- obligation. cause . span ) {
578- // Otherwise, if there is an on-unimplemented note,
579- // display it.
618+ obligation) {
619+ // If it has a custom "#[rustc_on_unimplemented]"
620+ // error message, let's display it!
580621 err. note ( & s) ;
581622 } else {
582623 let trait_ref = trait_predicate. to_poly_trait_ref ( ) ;
@@ -624,6 +665,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
624665 }
625666 err
626667 }
668+ // Check if it has a custom "#[rustc_on_unimplemented]"
669+ // error message, report with that message if it does
670+ /*let custom_note = report_on_unimplemented(infcx, &trait_ref.0,
671+ obligation);
672+ if let Some(s) = custom_note {
673+ err.fileline_note(obligation.cause.span, &s);
674+ } else {
675+ note_obligation_cause(infcx, &mut err, obligation);
676+ }*/
677+ err. emit ( ) ;
627678 }
628679
629680 ty:: Predicate :: Equate ( ref predicate) => {
0 commit comments