@@ -26,11 +26,11 @@ use super::{
2626
2727use fmt_macros:: { Parser , Piece , Position } ;
2828use hir:: def_id:: DefId ;
29- use infer:: { InferCtxt , TypeOrigin } ;
30- use ty:: { self , ToPredicate , ToPolyTraitRef , TraitRef , Ty , TyCtxt , TypeFoldable , TypeVariants } ;
29+ use infer:: { InferCtxt } ;
30+ use ty:: { self , ToPredicate , ToPolyTraitRef , Ty , TyCtxt , TypeFoldable } ;
3131use ty:: fast_reject;
3232use ty:: fold:: TypeFolder ;
33- use ty:: subst:: { self , ParamSpace , Subst } ;
33+ use ty:: subst:: { self , Subst } ;
3434use util:: nodemap:: { FnvHashMap , FnvHashSet } ;
3535
3636use std:: cmp;
@@ -61,128 +61,6 @@ impl<'a, 'gcx, 'tcx> TraitErrorKey<'tcx> {
6161 }
6262}
6363
64- // Enum used to differentiate the "big" and "little" weights.
65- enum Weight {
66- Coarse ,
67- Precise ,
68- }
69-
70- trait AssociatedWeight {
71- fn get_weight ( & self ) -> ( u32 , u32 ) ;
72- }
73-
74- impl < ' a > AssociatedWeight for TypeVariants < ' a > {
75- // Left number is for "global"/"big" weight and right number is for better precision.
76- fn get_weight ( & self ) -> ( u32 , u32 ) {
77- match * self {
78- TypeVariants :: TyBool => ( 1 , 1 ) ,
79- TypeVariants :: TyChar => ( 1 , 2 ) ,
80- TypeVariants :: TyStr => ( 1 , 3 ) ,
81-
82- TypeVariants :: TyInt ( _) => ( 2 , 1 ) ,
83- TypeVariants :: TyUint ( _) => ( 2 , 2 ) ,
84- TypeVariants :: TyFloat ( _) => ( 2 , 3 ) ,
85- TypeVariants :: TyRawPtr ( _) => ( 2 , 4 ) ,
86-
87- TypeVariants :: TyEnum ( _, _) => ( 3 , 1 ) ,
88- TypeVariants :: TyStruct ( _, _) => ( 3 , 2 ) ,
89- TypeVariants :: TyBox ( _) => ( 3 , 3 ) ,
90- TypeVariants :: TyTuple ( _) => ( 3 , 4 ) ,
91-
92- TypeVariants :: TyArray ( _, _) => ( 4 , 1 ) ,
93- TypeVariants :: TySlice ( _) => ( 4 , 2 ) ,
94-
95- TypeVariants :: TyRef ( _, _) => ( 5 , 1 ) ,
96- TypeVariants :: TyFnDef ( _, _, _) => ( 5 , 2 ) ,
97- TypeVariants :: TyFnPtr ( _) => ( 5 , 3 ) ,
98-
99- TypeVariants :: TyTrait ( _) => ( 6 , 1 ) ,
100-
101- TypeVariants :: TyClosure ( _, _) => ( 7 , 1 ) ,
102-
103- TypeVariants :: TyProjection ( _) => ( 8 , 1 ) ,
104- TypeVariants :: TyParam ( _) => ( 8 , 2 ) ,
105- TypeVariants :: TyInfer ( _) => ( 8 , 3 ) ,
106-
107- TypeVariants :: TyError => ( 9 , 1 ) ,
108- }
109- }
110- }
111-
112- // The "closer" the types are, the lesser the weight.
113- fn get_weight_diff ( a : & ty:: TypeVariants , b : & TypeVariants , weight : Weight ) -> u32 {
114- let ( w1, w2) = match weight {
115- Weight :: Coarse => ( a. get_weight ( ) . 0 , b. get_weight ( ) . 0 ) ,
116- Weight :: Precise => ( a. get_weight ( ) . 1 , b. get_weight ( ) . 1 ) ,
117- } ;
118- if w1 < w2 {
119- w2 - w1
120- } else {
121- w1 - w2
122- }
123- }
124-
125- // Once we have "globally matching" types, we need to run another filter on them.
126- //
127- // In the function `get_best_matching_type`, we got the types which might fit the
128- // most to the type we're looking for. This second filter now intends to get (if
129- // possible) the type which fits the most.
130- //
131- // For example, the trait expects an `usize` and here you have `u32` and `i32`.
132- // Obviously, the "correct" one is `u32`.
133- fn filter_matching_types < ' tcx > ( weights : & [ ( usize , u32 ) ] ,
134- imps : & [ ( DefId , subst:: Substs < ' tcx > ) ] ,
135- trait_types : & [ ty:: Ty < ' tcx > ] )
136- -> usize {
137- let matching_weight = weights[ 0 ] . 1 ;
138- let iter = weights. iter ( ) . filter ( |& & ( _, weight) | weight == matching_weight) ;
139- let mut filtered_weights = vec ! ( ) ;
140-
141- for & ( pos, _) in iter {
142- let mut weight = 0 ;
143- for ( type_to_compare, original_type) in imps[ pos] . 1
144- . types
145- . get_slice ( ParamSpace :: TypeSpace )
146- . iter ( )
147- . zip ( trait_types. iter ( ) ) {
148- weight += get_weight_diff ( & type_to_compare. sty , & original_type. sty , Weight :: Precise ) ;
149- }
150- filtered_weights. push ( ( pos, weight) ) ;
151- }
152- filtered_weights. sort_by ( |a, b| a. 1 . cmp ( & b. 1 ) ) ;
153- filtered_weights[ 0 ] . 0
154- }
155-
156- // Here, we run the "big" filter. Little example:
157- //
158- // We receive a `String`, an `u32` and an `i32`.
159- // The trait expected an `usize`.
160- // From human point of view, it's easy to determine that `String` doesn't correspond to
161- // the expected type at all whereas `u32` and `i32` could.
162- //
163- // This first filter intends to only keep the types which match the most.
164- fn get_best_matching_type < ' tcx > ( imps : & [ ( DefId , subst:: Substs < ' tcx > ) ] ,
165- trait_types : & [ ty:: Ty < ' tcx > ] ) -> usize {
166- let mut weights = vec ! ( ) ;
167- for ( pos, imp) in imps. iter ( ) . enumerate ( ) {
168- let mut weight = 0 ;
169- for ( type_to_compare, original_type) in imp. 1
170- . types
171- . get_slice ( ParamSpace :: TypeSpace )
172- . iter ( )
173- . zip ( trait_types. iter ( ) ) {
174- weight += get_weight_diff ( & type_to_compare. sty , & original_type. sty , Weight :: Coarse ) ;
175- }
176- weights. push ( ( pos, weight) ) ;
177- }
178- weights. sort_by ( |a, b| a. 1 . cmp ( & b. 1 ) ) ;
179- if weights[ 0 ] . 1 == weights[ 1 ] . 1 {
180- filter_matching_types ( & weights, & imps, trait_types)
181- } else {
182- weights[ 0 ] . 0
183- }
184- }
185-
18664impl < ' a , ' gcx , ' tcx > InferCtxt < ' a , ' gcx , ' tcx > {
18765 pub fn report_fulfillment_errors ( & self , errors : & Vec < FulfillmentError < ' tcx > > ) {
18866 for error in errors {
@@ -272,72 +150,46 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
272150 substs
273151 }
274152
275- fn get_current_failing_impl ( & self ,
276- trait_ref : & TraitRef < ' tcx > ,
277- obligation : & PredicateObligation < ' tcx > )
278- -> Option < ( DefId , subst:: Substs < ' tcx > ) > {
279- let simp = fast_reject:: simplify_type ( self . tcx ,
280- trait_ref. self_ty ( ) ,
281- true ) ;
282- let trait_def = self . tcx . lookup_trait_def ( trait_ref. def_id ) ;
283-
284- match simp {
285- Some ( _) => {
286- let mut matching_impls = Vec :: new ( ) ;
287- trait_def. for_each_impl ( self . tcx , |def_id| {
288- let imp = self . tcx . impl_trait_ref ( def_id) . unwrap ( ) ;
289- let substs = self . impl_substs ( def_id, obligation. clone ( ) ) ;
290- let imp = imp. subst ( self . tcx , & substs) ;
291-
292- if self . eq_types ( true ,
293- TypeOrigin :: Misc ( obligation. cause . span ) ,
294- trait_ref. self_ty ( ) ,
295- imp. self_ty ( ) ) . is_ok ( ) {
296- matching_impls. push ( ( def_id, imp. substs . clone ( ) ) ) ;
297- }
298- } ) ;
299- if matching_impls. len ( ) == 0 {
300- None
301- } else if matching_impls. len ( ) == 1 {
302- Some ( matching_impls[ 0 ] . clone ( ) )
303- } else {
304- let end = trait_ref. input_types ( ) . len ( ) - 1 ;
305- // we need to determine which type is the good one!
306- Some ( matching_impls[ get_best_matching_type ( & matching_impls,
307- & trait_ref. input_types ( ) [ 0 ..end] ) ]
308- . clone ( ) )
153+ fn impl_with_self_type_of ( & self ,
154+ trait_ref : ty:: PolyTraitRef < ' tcx > ,
155+ obligation : & PredicateObligation < ' tcx > )
156+ -> Option < DefId >
157+ {
158+ let tcx = self . tcx ;
159+ let mut result = None ;
160+ let mut ambiguous = false ;
161+
162+ let trait_self_ty = tcx. erase_late_bound_regions ( & trait_ref) . self_ty ( ) ;
163+
164+ self . tcx . lookup_trait_def ( trait_ref. def_id ( ) )
165+ . for_each_relevant_impl ( self . tcx , trait_self_ty, |def_id| {
166+ let impl_self_ty = tcx
167+ . impl_trait_ref ( def_id)
168+ . unwrap ( )
169+ . self_ty ( )
170+ . subst ( tcx, & self . impl_substs ( def_id, obligation. clone ( ) ) ) ;
171+
172+ if let Ok ( ..) = self . can_equate ( & trait_self_ty, & impl_self_ty) {
173+ ambiguous = result. is_some ( ) ;
174+ result = Some ( def_id) ;
309175 }
310- } ,
311- None => None ,
312- }
313- }
176+ } ) ;
314177
315- fn find_attr ( & self ,
316- def_id : DefId ,
317- attr_name : & str )
318- -> Option < ast:: Attribute > {
319- for item in self . tcx . get_attrs ( def_id) . iter ( ) {
320- if item. check_name ( attr_name) {
321- return Some ( item. clone ( ) ) ;
178+ match result {
179+ Some ( def_id) if !ambiguous && tcx. has_attr ( def_id, "rustc_on_unimplemented" ) => {
180+ result
322181 }
182+ _ => None
323183 }
324- None
325184 }
326185
327186 fn on_unimplemented_note ( & self ,
328187 trait_ref : ty:: PolyTraitRef < ' tcx > ,
329188 obligation : & PredicateObligation < ' tcx > ) -> Option < String > {
189+ let def_id = self . impl_with_self_type_of ( trait_ref, obligation)
190+ . unwrap_or ( trait_ref. def_id ( ) ) ;
330191 let trait_ref = trait_ref. skip_binder ( ) ;
331- let def_id = match self . get_current_failing_impl ( trait_ref, obligation) {
332- Some ( ( def_id, _) ) => {
333- if let Some ( _) = self . find_attr ( def_id, "rustc_on_unimplemented" ) {
334- def_id
335- } else {
336- trait_ref. def_id
337- }
338- } ,
339- None => trait_ref. def_id ,
340- } ;
192+
341193 let span = obligation. cause . span ;
342194 let mut report = None ;
343195 for item in self . tcx . get_attrs ( def_id) . iter ( ) {
0 commit comments