@@ -107,7 +107,7 @@ pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
107
107
}
108
108
}
109
109
110
- fn impl_self_ty < ' a , ' tcx > ( fcx : & InferCtxt < ' a , ' tcx > ,
110
+ fn impl_substs < ' a , ' tcx > ( fcx : & InferCtxt < ' a , ' tcx > ,
111
111
did : DefId ,
112
112
obligation : PredicateObligation < ' tcx > )
113
113
-> subst:: Substs < ' tcx > {
@@ -127,35 +127,65 @@ fn impl_self_ty<'a, 'tcx>(fcx: &InferCtxt<'a, 'tcx>,
127
127
substs
128
128
}
129
129
130
+ fn check_type_parameters < ' a , ' tcx > ( infcx : & InferCtxt < ' a , ' tcx > ,
131
+ trait_substs : & subst:: Substs < ' tcx > ,
132
+ impl_substs : & subst:: Substs < ' tcx > ,
133
+ obligation : & PredicateObligation < ' tcx > ) -> bool {
134
+ let trait_types = trait_substs. types . as_slice ( ) ;
135
+ let impl_types = impl_substs. types . as_slice ( ) ;
136
+
137
+ let mut failed = 0 ;
138
+ for index_to_ignore in 0 ..trait_types. len ( ) {
139
+ for ( index, ( trait_type, impl_type) ) in trait_types. iter ( )
140
+ . zip ( impl_types. iter ( ) )
141
+ . enumerate ( ) {
142
+ if index_to_ignore != index &&
143
+ infer:: mk_eqty ( infcx, true ,
144
+ TypeOrigin :: Misc ( obligation. cause . span ) ,
145
+ trait_type,
146
+ impl_type) . is_err ( ) {
147
+ failed += 1 ;
148
+ break ;
149
+ }
150
+ }
151
+ }
152
+ failed == trait_types. len ( ) - 1
153
+ }
154
+
130
155
fn get_current_failing_impl < ' a , ' tcx > ( infcx : & InferCtxt < ' a , ' tcx > ,
131
156
trait_ref : & TraitRef < ' tcx > ,
132
157
obligation : & PredicateObligation < ' tcx > )
133
- -> Option < DefId > {
158
+ -> Option < ( DefId , subst :: Substs < ' tcx > ) > {
134
159
let simp = fast_reject:: simplify_type ( infcx. tcx ,
135
160
trait_ref. self_ty ( ) ,
136
161
true ) ;
137
162
let trait_def = infcx. tcx . lookup_trait_def ( trait_ref. def_id ) ;
138
163
139
164
match simp {
140
165
Some ( _) => {
141
- let mut ret = None ;
166
+ let mut matching_impls = Vec :: new ( ) ;
142
167
trait_def. for_each_impl ( infcx. tcx , |def_id| {
143
168
let imp = infcx. tcx . impl_trait_ref ( def_id) . unwrap ( ) ;
144
- let imp = imp. subst ( infcx. tcx , & impl_self_ty ( infcx, def_id, obligation. clone ( ) ) ) ;
145
- if ret. is_none ( ) {
146
- for error in infcx. reported_trait_errors . borrow ( ) . iter ( ) {
147
- if let ty:: Predicate :: Trait ( ref t) = error. predicate {
148
- if infer:: mk_eqty ( infcx, true , TypeOrigin :: Misc ( obligation. cause . span ) ,
149
- t. skip_binder ( ) . trait_ref . self_ty ( ) ,
150
- imp. self_ty ( ) ) . is_ok ( ) {
151
- ret = Some ( def_id) ;
152
- break ;
153
- }
154
- }
169
+ let substs = impl_substs ( infcx, def_id, obligation. clone ( ) ) ;
170
+ let imp = imp. subst ( infcx. tcx , & substs) ;
171
+
172
+ if infer:: mk_eqty ( infcx, true ,
173
+ TypeOrigin :: Misc ( obligation. cause . span ) ,
174
+ trait_ref. self_ty ( ) ,
175
+ imp. self_ty ( ) ) . is_ok ( ) {
176
+ if check_type_parameters ( infcx, & trait_ref. substs , & imp. substs , obligation) {
177
+ matching_impls. push ( ( def_id, imp. substs . clone ( ) ) ) ;
155
178
}
156
179
}
157
180
} ) ;
158
- ret
181
+ if matching_impls. len ( ) == 0 {
182
+ None
183
+ } else if matching_impls. len ( ) == 1 {
184
+ Some ( matching_impls[ 0 ] . clone ( ) )
185
+ } else {
186
+ // we need to determine which type is the good one!
187
+ Some ( matching_impls[ 0 ] . clone ( ) )
188
+ }
159
189
} ,
160
190
None => None ,
161
191
}
@@ -178,14 +208,14 @@ fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
178
208
obligation : & PredicateObligation < ' tcx > )
179
209
-> Option < String > {
180
210
let def_id = match get_current_failing_impl ( infcx, trait_ref, obligation) {
181
- Some ( def_id) => {
211
+ Some ( ( def_id, _ ) ) => {
182
212
if let Some ( _) = find_attr ( infcx, def_id, "rustc_on_unimplemented" ) {
183
213
def_id
184
214
} else {
185
215
trait_ref. def_id
186
216
}
187
217
} ,
188
- None => trait_ref. def_id ,
218
+ None => trait_ref. def_id ,
189
219
} ;
190
220
let span = obligation. cause . span ;
191
221
let mut report = None ;
0 commit comments