@@ -174,6 +174,53 @@ fn on_unimplemented_note<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
174174 report
175175}
176176
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+
177224/// Reports that an overflow has occurred and halts compilation. We
178225/// halt compilation unconditionally because it is important that
179226/// overflows never be masked -- they basically represent computations
@@ -364,59 +411,35 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
364411 "the trait bound `{}` is not satisfied" ,
365412 trait_ref. to_predicate( ) ) ;
366413
367- // Try to report a good error message.
414+ // Try to report a help message
368415
369416 if !trait_ref. has_infer_types ( ) &&
370417 predicate_can_apply ( infcx, trait_ref)
371418 {
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.
372426 err. fileline_help ( obligation. cause . span , & format ! (
373427 "consider adding a `where {}` bound" ,
374428 trait_ref. to_predicate( )
375429 ) ) ;
376430 } else if let Some ( s) = on_unimplemented_note ( infcx, trait_ref,
377431 obligation. cause . span ) {
432+ // Otherwise, if there is an on-unimplemented note,
433+ // display it.
378434 err. fileline_note ( obligation. cause . span , & s) ;
379435 } 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.
404438
439+ let impl_candidates = find_similar_impl_candidates ( infcx, trait_ref) ;
405440 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) ;
420443 }
421444 }
422445 note_obligation_cause ( infcx, & mut err, obligation) ;
0 commit comments