@@ -174,6 +174,53 @@ fn on_unimplemented_note<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
174
174
report
175
175
}
176
176
177
+ fn find_similar_impl_candidates < ' a , ' tcx > (
178
+ infcx : & InferCtxt < ' a , ' tcx > ,
179
+ trait_ref : ty:: PolyTraitRef < ' tcx > )
180
+ -> Vec < ty:: TraitRef < ' tcx > >
181
+ {
182
+ let simp = fast_reject:: simplify_type ( infcx. tcx ,
183
+ trait_ref. skip_binder ( ) . self_ty ( ) ,
184
+ true ) ;
185
+ let mut impl_candidates = Vec :: new ( ) ;
186
+ let trait_def = infcx. tcx . lookup_trait_def ( trait_ref. def_id ( ) ) ;
187
+
188
+ match simp {
189
+ Some ( simp) => trait_def. for_each_impl ( infcx. tcx , |def_id| {
190
+ let imp = infcx. tcx . impl_trait_ref ( def_id) . unwrap ( ) ;
191
+ let imp_simp = fast_reject:: simplify_type ( infcx. tcx ,
192
+ imp. self_ty ( ) ,
193
+ true ) ;
194
+ if let Some ( imp_simp) = imp_simp {
195
+ if simp != imp_simp {
196
+ return ;
197
+ }
198
+ }
199
+ impl_candidates. push ( imp) ;
200
+ } ) ,
201
+ None => trait_def. for_each_impl ( infcx. tcx , |def_id| {
202
+ impl_candidates. push (
203
+ infcx. tcx . impl_trait_ref ( def_id) . unwrap ( ) ) ;
204
+ } )
205
+ } ;
206
+ impl_candidates
207
+ }
208
+
209
+ fn report_similar_impl_candidates ( span : Span ,
210
+ err : & mut DiagnosticBuilder ,
211
+ impl_candidates : & [ ty:: TraitRef ] )
212
+ {
213
+ err. fileline_help ( span, & format ! ( "the following implementations were found:" ) ) ;
214
+
215
+ let end = cmp:: min ( 4 , impl_candidates. len ( ) ) ;
216
+ for candidate in & impl_candidates[ 0 ..end] {
217
+ err. fileline_help ( span, & format ! ( " {:?}" , candidate) ) ;
218
+ }
219
+ if impl_candidates. len ( ) > 4 {
220
+ err. fileline_help ( span, & format ! ( "and {} others" , impl_candidates. len( ) -4 ) ) ;
221
+ }
222
+ }
223
+
177
224
/// Reports that an overflow has occurred and halts compilation. We
178
225
/// halt compilation unconditionally because it is important that
179
226
/// overflows never be masked -- they basically represent computations
@@ -364,59 +411,35 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
364
411
"the trait bound `{}` is not satisfied" ,
365
412
trait_ref. to_predicate( ) ) ;
366
413
367
- // Try to report a good error message.
414
+ // Try to report a help message
368
415
369
416
if !trait_ref. has_infer_types ( ) &&
370
417
predicate_can_apply ( infcx, trait_ref)
371
418
{
419
+ // If a where-clause may be useful, remind the
420
+ // user that they can add it.
421
+ //
422
+ // don't display an on-unimplemented note, as
423
+ // these notes will often be of the form
424
+ // "the type `T` can't be frobnicated"
425
+ // which is somewhat confusing.
372
426
err. fileline_help ( obligation. cause . span , & format ! (
373
427
"consider adding a `where {}` bound" ,
374
428
trait_ref. to_predicate( )
375
429
) ) ;
376
430
} else if let Some ( s) = on_unimplemented_note ( infcx, trait_ref,
377
431
obligation. cause . span ) {
432
+ // Otherwise, if there is an on-unimplemented note,
433
+ // display it.
378
434
err. fileline_note ( obligation. cause . span , & s) ;
379
435
} else {
380
- let simp = fast_reject:: simplify_type ( infcx. tcx ,
381
- trait_ref. self_ty ( ) ,
382
- true ) ;
383
- let mut impl_candidates = Vec :: new ( ) ;
384
- let trait_def = infcx. tcx . lookup_trait_def ( trait_ref. def_id ( ) ) ;
385
-
386
- match simp {
387
- Some ( simp) => trait_def. for_each_impl ( infcx. tcx , |def_id| {
388
- let imp = infcx. tcx . impl_trait_ref ( def_id) . unwrap ( ) ;
389
- let imp_simp = fast_reject:: simplify_type ( infcx. tcx ,
390
- imp. self_ty ( ) ,
391
- true ) ;
392
- if let Some ( imp_simp) = imp_simp {
393
- if simp != imp_simp {
394
- return ;
395
- }
396
- }
397
- impl_candidates. push ( imp) ;
398
- } ) ,
399
- None => trait_def. for_each_impl ( infcx. tcx , |def_id| {
400
- impl_candidates. push (
401
- infcx. tcx . impl_trait_ref ( def_id) . unwrap ( ) ) ;
402
- } )
403
- } ;
436
+ // If we can't show anything useful, try to find
437
+ // similar impls.
404
438
439
+ let impl_candidates = find_similar_impl_candidates ( infcx, trait_ref) ;
405
440
if impl_candidates. len ( ) > 0 {
406
- err. fileline_help (
407
- obligation. cause . span ,
408
- & format ! ( "the following implementations were found:" ) ) ;
409
-
410
- let end = cmp:: min ( 4 , impl_candidates. len ( ) ) ;
411
- for candidate in & impl_candidates[ 0 ..end] {
412
- err. fileline_help ( obligation. cause . span ,
413
- & format ! ( " {:?}" , candidate) ) ;
414
- }
415
- if impl_candidates. len ( ) > 4 {
416
- err. fileline_help ( obligation. cause . span ,
417
- & format ! ( "and {} others" ,
418
- impl_candidates. len( ) -4 ) ) ;
419
- }
441
+ report_similar_impl_candidates ( obligation. cause . span ,
442
+ & mut err, & impl_candidates) ;
420
443
}
421
444
}
422
445
note_obligation_cause ( infcx, & mut err, obligation) ;
0 commit comments