@@ -26,11 +26,11 @@ use super::{
26
26
27
27
use fmt_macros:: { Parser , Piece , Position } ;
28
28
use 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 } ;
31
31
use ty:: fast_reject;
32
32
use ty:: fold:: TypeFolder ;
33
- use ty:: subst:: { self , ParamSpace , Subst } ;
33
+ use ty:: subst:: { self , Subst } ;
34
34
use util:: nodemap:: { FnvHashMap , FnvHashSet } ;
35
35
36
36
use std:: cmp;
@@ -61,128 +61,6 @@ impl<'a, 'gcx, 'tcx> TraitErrorKey<'tcx> {
61
61
}
62
62
}
63
63
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
-
186
64
impl < ' a , ' gcx , ' tcx > InferCtxt < ' a , ' gcx , ' tcx > {
187
65
pub fn report_fulfillment_errors ( & self , errors : & Vec < FulfillmentError < ' tcx > > ) {
188
66
for error in errors {
@@ -272,72 +150,46 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
272
150
substs
273
151
}
274
152
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) ;
309
175
}
310
- } ,
311
- None => None ,
312
- }
313
- }
176
+ } ) ;
314
177
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
322
181
}
182
+ _ => None
323
183
}
324
- None
325
184
}
326
185
327
186
fn on_unimplemented_note ( & self ,
328
187
trait_ref : ty:: PolyTraitRef < ' tcx > ,
329
188
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 ( ) ) ;
330
191
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
+
341
193
let span = obligation. cause . span ;
342
194
let mut report = None ;
343
195
for item in self . tcx . get_attrs ( def_id) . iter ( ) {
0 commit comments