@@ -66,6 +66,8 @@ crate struct ImportSuggestion {
66
66
pub descr : & ' static str ,
67
67
pub path : Path ,
68
68
pub accessible : bool ,
69
+ /// An extra note that should be issued if this item is suggested
70
+ pub note : Option < String > ,
69
71
}
70
72
71
73
/// Adjust the impl span so that just the `impl` keyword is taken by removing
@@ -872,11 +874,38 @@ impl<'a> Resolver<'a> {
872
874
}
873
875
874
876
if candidates. iter ( ) . all ( |v : & ImportSuggestion | v. did != did) {
877
+ // See if we're recommending TryFrom, TryInto, or FromIterator and add
878
+ // a note about editions
879
+ let note = if let Some ( did) = did {
880
+ let requires_note = !did. is_local ( )
881
+ && this. cstore ( ) . item_attrs ( did, this. session ) . iter ( ) . any (
882
+ |attr| {
883
+ if attr. has_name ( sym:: rustc_diagnostic_item) {
884
+ [ sym:: TryInto , sym:: TryFrom , sym:: FromIterator ]
885
+ . map ( |x| Some ( x) )
886
+ . contains ( & attr. value_str ( ) )
887
+ } else {
888
+ false
889
+ }
890
+ } ,
891
+ ) ;
892
+
893
+ requires_note. then ( || {
894
+ format ! (
895
+ "'{}' is included in the prelude starting in Edition 2021" ,
896
+ path_names_to_string( & path)
897
+ )
898
+ } )
899
+ } else {
900
+ None
901
+ } ;
902
+
875
903
candidates. push ( ImportSuggestion {
876
904
did,
877
905
descr : res. descr ( ) ,
878
906
path,
879
907
accessible : child_accessible,
908
+ note,
880
909
} ) ;
881
910
}
882
911
}
@@ -1764,12 +1793,14 @@ crate fn show_candidates(
1764
1793
return ;
1765
1794
}
1766
1795
1767
- let mut accessible_path_strings: Vec < ( String , & str , Option < DefId > ) > = Vec :: new ( ) ;
1768
- let mut inaccessible_path_strings: Vec < ( String , & str , Option < DefId > ) > = Vec :: new ( ) ;
1796
+ let mut accessible_path_strings: Vec < ( String , & str , Option < DefId > , & Option < String > ) > =
1797
+ Vec :: new ( ) ;
1798
+ let mut inaccessible_path_strings: Vec < ( String , & str , Option < DefId > , & Option < String > ) > =
1799
+ Vec :: new ( ) ;
1769
1800
1770
1801
candidates. iter ( ) . for_each ( |c| {
1771
1802
( if c. accessible { & mut accessible_path_strings } else { & mut inaccessible_path_strings } )
1772
- . push ( ( path_names_to_string ( & c. path ) , c. descr , c. did ) )
1803
+ . push ( ( path_names_to_string ( & c. path ) , c. descr , c. did , & c . note ) )
1773
1804
} ) ;
1774
1805
1775
1806
// we want consistent results across executions, but candidates are produced
@@ -1792,6 +1823,10 @@ crate fn show_candidates(
1792
1823
let instead = if instead { " instead" } else { "" } ;
1793
1824
let mut msg = format ! ( "consider importing {} {}{}" , determiner, kind, instead) ;
1794
1825
1826
+ for note in accessible_path_strings. iter ( ) . map ( |cand| cand. 3 . as_ref ( ) ) . flatten ( ) {
1827
+ err. note ( note) ;
1828
+ }
1829
+
1795
1830
if let Some ( span) = use_placement_span {
1796
1831
for candidate in & mut accessible_path_strings {
1797
1832
// produce an additional newline to separate the new use statement
@@ -1820,7 +1855,7 @@ crate fn show_candidates(
1820
1855
assert ! ( !inaccessible_path_strings. is_empty( ) ) ;
1821
1856
1822
1857
if inaccessible_path_strings. len ( ) == 1 {
1823
- let ( name, descr, def_id) = & inaccessible_path_strings[ 0 ] ;
1858
+ let ( name, descr, def_id, note ) = & inaccessible_path_strings[ 0 ] ;
1824
1859
let msg = format ! ( "{} `{}` exists but is inaccessible" , descr, name) ;
1825
1860
1826
1861
if let Some ( local_def_id) = def_id. and_then ( |did| did. as_local ( ) ) {
@@ -1832,12 +1867,15 @@ crate fn show_candidates(
1832
1867
} else {
1833
1868
err. note ( & msg) ;
1834
1869
}
1870
+ if let Some ( note) = ( * note) . as_deref ( ) {
1871
+ err. note ( note) ;
1872
+ }
1835
1873
} else {
1836
- let ( _, descr_first, _) = & inaccessible_path_strings[ 0 ] ;
1874
+ let ( _, descr_first, _, _ ) = & inaccessible_path_strings[ 0 ] ;
1837
1875
let descr = if inaccessible_path_strings
1838
1876
. iter ( )
1839
1877
. skip ( 1 )
1840
- . all ( |( _, descr, _) | descr == descr_first)
1878
+ . all ( |( _, descr, _, _ ) | descr == descr_first)
1841
1879
{
1842
1880
descr_first. to_string ( )
1843
1881
} else {
@@ -1848,7 +1886,7 @@ crate fn show_candidates(
1848
1886
let mut has_colon = false ;
1849
1887
1850
1888
let mut spans = Vec :: new ( ) ;
1851
- for ( name, _, def_id) in & inaccessible_path_strings {
1889
+ for ( name, _, def_id, _ ) in & inaccessible_path_strings {
1852
1890
if let Some ( local_def_id) = def_id. and_then ( |did| did. as_local ( ) ) {
1853
1891
let span = definitions. def_span ( local_def_id) ;
1854
1892
let span = session. source_map ( ) . guess_head_span ( span) ;
@@ -1868,6 +1906,10 @@ crate fn show_candidates(
1868
1906
multi_span. push_span_label ( span, format ! ( "`{}`: not accessible" , name) ) ;
1869
1907
}
1870
1908
1909
+ for note in inaccessible_path_strings. iter ( ) . map ( |cand| cand. 3 . as_ref ( ) ) . flatten ( ) {
1910
+ err. note ( note) ;
1911
+ }
1912
+
1871
1913
err. span_note ( multi_span, & msg) ;
1872
1914
}
1873
1915
}
0 commit comments