@@ -29,8 +29,8 @@ use hir::def_id::DefId;
29
29
use infer:: { self , InferCtxt , TypeOrigin } ;
30
30
use ty:: { self , ToPredicate , ToPolyTraitRef , TraitRef , Ty , TyCtxt , TypeFoldable } ;
31
31
use 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 } ;
34
34
use util:: nodemap:: { FnvHashMap , FnvHashSet } ;
35
35
36
36
use std:: cmp;
@@ -62,7 +62,7 @@ impl<'a, 'gcx, 'tcx> TraitErrorKey<'tcx> {
62
62
}
63
63
}
64
64
65
- fn impl_self_ty < ' a , ' tcx > ( fcx : & InferCtxt < ' a , ' tcx > ,
65
+ fn impl_substs < ' a , ' tcx > ( fcx : & InferCtxt < ' a , ' tcx > ,
66
66
did : DefId ,
67
67
obligation : PredicateObligation < ' tcx > )
68
68
-> subst:: Substs < ' tcx > {
@@ -82,35 +82,74 @@ fn impl_self_ty<'a, 'tcx>(fcx: &InferCtxt<'a, 'tcx>,
82
82
substs
83
83
}
84
84
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
+
85
110
fn get_current_failing_impl < ' a , ' tcx > ( infcx : & InferCtxt < ' a , ' tcx > ,
86
111
trait_ref : & TraitRef < ' tcx > ,
87
112
obligation : & PredicateObligation < ' tcx > )
88
- -> Option < DefId > {
113
+ -> Option < ( DefId , subst:: Substs < ' tcx > ) > {
114
+ println ! ( "1" ) ;
89
115
let simp = fast_reject:: simplify_type ( infcx. tcx ,
90
116
trait_ref. self_ty ( ) ,
91
117
true ) ;
92
118
let trait_def = infcx. tcx . lookup_trait_def ( trait_ref. def_id ) ;
93
119
94
120
match simp {
95
121
Some ( _) => {
96
- let mut ret = None ;
122
+ println ! ( "2" ) ;
123
+ let mut matching_impls = Vec :: new ( ) ;
97
124
trait_def. for_each_impl ( infcx. tcx , |def_id| {
98
125
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
+ //}
111
136
}
137
+ println ! ( "=> {:?} /// {:?}" , def_id, imp. substs) ;
112
138
} ) ;
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
+ }
114
153
} ,
115
154
None => None ,
116
155
}
@@ -128,19 +167,21 @@ fn find_attr<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
128
167
None
129
168
}
130
169
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 ;
135
176
let def_id = match get_current_failing_impl ( infcx, trait_ref, obligation) {
136
- Some ( def_id) => {
177
+ Some ( ( def_id, _ ) ) => {
137
178
if let Some ( _) = find_attr ( infcx, def_id, "rustc_on_unimplemented" ) {
138
179
def_id
139
180
} else {
140
181
trait_ref. def_id
141
182
}
142
183
} ,
143
- None => trait_ref. def_id ,
184
+ None => trait_ref. def_id ,
144
185
} ;
145
186
let span = obligation. cause . span ;
146
187
let mut report = None ;
@@ -572,11 +613,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
572
613
// "the type `T` can't be frobnicated"
573
614
// which is somewhat confusing.
574
615
err. help ( & format ! ( "consider adding a `where {}` bound" ,
575
- trait_ref. to_predicate( ) ) ) ;
616
+ trait_ref. to_predicate( ) ) ) ;
576
617
} 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!
580
621
err. note ( & s) ;
581
622
} else {
582
623
let trait_ref = trait_predicate. to_poly_trait_ref ( ) ;
@@ -624,6 +665,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
624
665
}
625
666
err
626
667
}
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 ( ) ;
627
678
}
628
679
629
680
ty:: Predicate :: Equate ( ref predicate) => {
0 commit comments