@@ -30,7 +30,7 @@ use rustc_middle::traits::select::OverflowError;
30
30
use rustc_middle:: ty:: error:: ExpectedFound ;
31
31
use rustc_middle:: ty:: fold:: TypeFolder ;
32
32
use rustc_middle:: ty:: {
33
- self , SubtypePredicate , ToPolyTraitRef , ToPredicate , Ty , TyCtxt , TypeFoldable ,
33
+ self , SubtypePredicate , ToPolyTraitRef , ToPredicate , TraitRef , Ty , TyCtxt , TypeFoldable ,
34
34
} ;
35
35
use rustc_span:: symbol:: { kw, sym} ;
36
36
use rustc_span:: { ExpnKind , MultiSpan , Span , DUMMY_SP } ;
@@ -1756,6 +1756,60 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
1756
1756
trait_ref : ty:: PolyTraitRef < ' tcx > ,
1757
1757
err : & mut Diagnostic ,
1758
1758
) -> 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
+
1759
1813
let def_id = trait_ref. def_id ( ) ;
1760
1814
if impl_candidates. is_empty ( ) {
1761
1815
if self . tcx . trait_is_auto ( def_id)
@@ -1765,7 +1819,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
1765
1819
// Mentioning implementers of `Copy`, `Debug` and friends is not useful.
1766
1820
return false ;
1767
1821
}
1768
- let mut normalized_impl_candidates: Vec < _ > = self
1822
+ let normalized_impl_candidates: Vec < _ > = self
1769
1823
. tcx
1770
1824
. all_impls ( def_id)
1771
1825
// Ignore automatically derived impls and `!Trait` impls.
@@ -1776,54 +1830,19 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
1776
1830
. filter_map ( |def_id| self . tcx . impl_trait_ref ( def_id) )
1777
1831
// Avoid mentioning type parameters.
1778
1832
. filter ( |trait_ref| !matches ! ( trait_ref. self_ty( ) . kind( ) , ty:: Param ( _) ) )
1779
- . map ( |trait_ref| format ! ( "\n {}" , trait_ref. self_ty( ) ) )
1780
1833
. 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) ;
1813
1835
}
1814
1836
1815
- let len = impl_candidates. len ( ) ;
1816
- let end = if impl_candidates. len ( ) <= 9 { impl_candidates. len ( ) } else { 8 } ;
1817
-
1818
1837
let normalize = |candidate| {
1819
1838
self . tcx . infer_ctxt ( ) . enter ( |ref infcx| {
1820
1839
let normalized = infcx
1821
1840
. at ( & ObligationCause :: dummy ( ) , ty:: ParamEnv :: empty ( ) )
1822
1841
. normalize ( candidate)
1823
1842
. ok ( ) ;
1824
1843
match normalized {
1825
- Some ( normalized) => format ! ( " \n {}" , normalized. value) ,
1826
- None => format ! ( " \n {}" , candidate) ,
1844
+ Some ( normalized) => normalized. value ,
1845
+ None => candidate,
1827
1846
}
1828
1847
} )
1829
1848
} ;
@@ -1834,7 +1853,6 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
1834
1853
//
1835
1854
// Prefer more similar candidates first, then sort lexicographically
1836
1855
// by their normalized string representation.
1837
- let first_candidate = impl_candidates. get ( 0 ) . map ( |candidate| candidate. trait_ref ) ;
1838
1856
let mut normalized_impl_candidates_and_similarities = impl_candidates
1839
1857
. into_iter ( )
1840
1858
. map ( |ImplCandidate { trait_ref, similarity } | {
@@ -1850,26 +1868,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
1850
1868
. map ( |( _, normalized) | normalized)
1851
1869
. collect :: < Vec < _ > > ( ) ;
1852
1870
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)
1873
1872
}
1874
1873
1875
1874
/// Gets the parent trait chain start
0 commit comments