@@ -30,7 +30,7 @@ use rustc_middle::traits::select::OverflowError;
3030use rustc_middle:: ty:: error:: ExpectedFound ;
3131use rustc_middle:: ty:: fold:: TypeFolder ;
3232use rustc_middle:: ty:: {
33- self , SubtypePredicate , ToPolyTraitRef , ToPredicate , Ty , TyCtxt , TypeFoldable ,
33+ self , SubtypePredicate , ToPolyTraitRef , ToPredicate , TraitRef , Ty , TyCtxt , TypeFoldable ,
3434} ;
3535use rustc_span:: symbol:: { kw, sym} ;
3636use rustc_span:: { ExpnKind , MultiSpan , Span , DUMMY_SP } ;
@@ -1756,6 +1756,60 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
17561756 trait_ref : ty:: PolyTraitRef < ' tcx > ,
17571757 err : & mut Diagnostic ,
17581758 ) -> bool {
1759+ let report = |mut candidates : Vec < TraitRef < ' _ > > , err : & mut Diagnostic | {
1760+ candidates. sort ( ) ;
1761+ candidates. dedup ( ) ;
1762+ let len = candidates. len ( ) ;
1763+ if candidates. len ( ) == 0 {
1764+ return false ;
1765+ }
1766+ let trait_ref = candidates[ 0 ] ;
1767+ if candidates. len ( ) == 1 {
1768+ err. highlighted_help ( vec ! [
1769+ (
1770+ format!(
1771+ "the trait `{}` is implemented for `" ,
1772+ trait_ref. print_only_trait_path( )
1773+ ) ,
1774+ Style :: NoStyle ,
1775+ ) ,
1776+ ( candidates[ 0 ] . self_ty( ) . to_string( ) , Style :: Highlight ) ,
1777+ ( "`" . to_string( ) , Style :: NoStyle ) ,
1778+ ] ) ;
1779+ return true ;
1780+ }
1781+ // Check if the trait is the same in all cases. If so, we'll only show the type.
1782+ // FIXME: there *has* to be a better way!
1783+ let mut traits: Vec < _ > = candidates
1784+ . iter ( )
1785+ . map ( |c| format ! ( "{}" , c) . split ( " as " ) . last ( ) . unwrap ( ) . to_string ( ) )
1786+ . collect ( ) ;
1787+ traits. sort ( ) ;
1788+ traits. dedup ( ) ;
1789+
1790+ let mut candidates: Vec < String > = candidates
1791+ . into_iter ( )
1792+ . map ( |c| {
1793+ if traits. len ( ) == 1 {
1794+ format ! ( "\n {}" , c. self_ty( ) )
1795+ } else {
1796+ format ! ( "\n {}" , c)
1797+ }
1798+ } )
1799+ . collect ( ) ;
1800+
1801+ candidates. sort ( ) ;
1802+ candidates. dedup ( ) ;
1803+ let end = if candidates. len ( ) <= 9 { candidates. len ( ) } else { 8 } ;
1804+ err. help ( & format ! (
1805+ "the following other types implement trait `{}`:{}{}" ,
1806+ trait_ref. print_only_trait_path( ) ,
1807+ candidates[ ..end] . join( "" ) ,
1808+ if len > 9 { format!( "\n and {} others" , len - 8 ) } else { String :: new( ) }
1809+ ) ) ;
1810+ true
1811+ } ;
1812+
17591813 let def_id = trait_ref. def_id ( ) ;
17601814 if impl_candidates. is_empty ( ) {
17611815 if self . tcx . trait_is_auto ( def_id)
@@ -1765,7 +1819,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
17651819 // Mentioning implementers of `Copy`, `Debug` and friends is not useful.
17661820 return false ;
17671821 }
1768- let mut normalized_impl_candidates: Vec < _ > = self
1822+ let normalized_impl_candidates: Vec < _ > = self
17691823 . tcx
17701824 . all_impls ( def_id)
17711825 // Ignore automatically derived impls and `!Trait` impls.
@@ -1776,54 +1830,19 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
17761830 . filter_map ( |def_id| self . tcx . impl_trait_ref ( def_id) )
17771831 // Avoid mentioning type parameters.
17781832 . filter ( |trait_ref| !matches ! ( trait_ref. self_ty( ) . kind( ) , ty:: Param ( _) ) )
1779- . map ( |trait_ref| format ! ( "\n {}" , trait_ref. self_ty( ) ) )
17801833 . collect ( ) ;
1781- normalized_impl_candidates. sort ( ) ;
1782- normalized_impl_candidates. dedup ( ) ;
1783- let len = normalized_impl_candidates. len ( ) ;
1784- if len == 0 {
1785- return false ;
1786- }
1787- if len == 1 {
1788- err. highlighted_help ( vec ! [
1789- (
1790- format!(
1791- "the trait `{}` is implemented for `" ,
1792- trait_ref. print_only_trait_path( )
1793- ) ,
1794- Style :: NoStyle ,
1795- ) ,
1796- ( normalized_impl_candidates[ 0 ] . trim( ) . to_string( ) , Style :: Highlight ) ,
1797- ( "`" . to_string( ) , Style :: NoStyle ) ,
1798- ] ) ;
1799- return true ;
1800- }
1801- let end = if normalized_impl_candidates. len ( ) <= 9 {
1802- normalized_impl_candidates. len ( )
1803- } else {
1804- 8
1805- } ;
1806- err. help ( & format ! (
1807- "the following other types implement trait `{}`:{}{}" ,
1808- trait_ref. print_only_trait_path( ) ,
1809- normalized_impl_candidates[ ..end] . join( "" ) ,
1810- if len > 9 { format!( "\n and {} others" , len - 8 ) } else { String :: new( ) }
1811- ) ) ;
1812- return true ;
1834+ return report ( normalized_impl_candidates, err) ;
18131835 }
18141836
1815- let len = impl_candidates. len ( ) ;
1816- let end = if impl_candidates. len ( ) <= 9 { impl_candidates. len ( ) } else { 8 } ;
1817-
18181837 let normalize = |candidate| {
18191838 self . tcx . infer_ctxt ( ) . enter ( |ref infcx| {
18201839 let normalized = infcx
18211840 . at ( & ObligationCause :: dummy ( ) , ty:: ParamEnv :: empty ( ) )
18221841 . normalize ( candidate)
18231842 . ok ( ) ;
18241843 match normalized {
1825- Some ( normalized) => format ! ( " \n {}" , normalized. value) ,
1826- None => format ! ( " \n {}" , candidate) ,
1844+ Some ( normalized) => normalized. value ,
1845+ None => candidate,
18271846 }
18281847 } )
18291848 } ;
@@ -1834,7 +1853,6 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
18341853 //
18351854 // Prefer more similar candidates first, then sort lexicographically
18361855 // by their normalized string representation.
1837- let first_candidate = impl_candidates. get ( 0 ) . map ( |candidate| candidate. trait_ref ) ;
18381856 let mut normalized_impl_candidates_and_similarities = impl_candidates
18391857 . into_iter ( )
18401858 . map ( |ImplCandidate { trait_ref, similarity } | {
@@ -1850,26 +1868,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
18501868 . map ( |( _, normalized) | normalized)
18511869 . collect :: < Vec < _ > > ( ) ;
18521870
1853- if normalized_impl_candidates. len ( ) == 1 {
1854- err. highlighted_help ( vec ! [
1855- (
1856- format!(
1857- "the trait `{}` is implemented for `" ,
1858- first_candidate. unwrap( ) . print_only_trait_path( )
1859- ) ,
1860- Style :: NoStyle ,
1861- ) ,
1862- ( first_candidate. unwrap( ) . self_ty( ) . to_string( ) , Style :: Highlight ) ,
1863- ( "`" . to_string( ) , Style :: NoStyle ) ,
1864- ] ) ;
1865- } else {
1866- err. help ( & format ! (
1867- "the following implementations were found:{}{}" ,
1868- normalized_impl_candidates[ ..end] . join( "" ) ,
1869- if len > 9 { format!( "\n and {} others" , len - 8 ) } else { String :: new( ) }
1870- ) ) ;
1871- }
1872- true
1871+ report ( normalized_impl_candidates, err)
18731872 }
18741873
18751874 /// Gets the parent trait chain start
0 commit comments