@@ -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,11 @@ 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
+ // Issue notes
1827
+ for note in accessible_path_strings. iter ( ) . map ( |cand| cand. 3 . as_ref ( ) ) . flatten ( ) {
1828
+ err. note ( note) ;
1829
+ }
1830
+
1795
1831
if let Some ( span) = use_placement_span {
1796
1832
for candidate in & mut accessible_path_strings {
1797
1833
// produce an additional newline to separate the new use statement
@@ -1820,7 +1856,7 @@ crate fn show_candidates(
1820
1856
assert ! ( !inaccessible_path_strings. is_empty( ) ) ;
1821
1857
1822
1858
if inaccessible_path_strings. len ( ) == 1 {
1823
- let ( name, descr, def_id) = & inaccessible_path_strings[ 0 ] ;
1859
+ let ( name, descr, def_id, note ) = & inaccessible_path_strings[ 0 ] ;
1824
1860
let msg = format ! ( "{} `{}` exists but is inaccessible" , descr, name) ;
1825
1861
1826
1862
if let Some ( local_def_id) = def_id. and_then ( |did| did. as_local ( ) ) {
@@ -1832,12 +1868,15 @@ crate fn show_candidates(
1832
1868
} else {
1833
1869
err. note ( & msg) ;
1834
1870
}
1871
+ if let Some ( note) = ( * note) . as_deref ( ) {
1872
+ err. note ( note) ;
1873
+ }
1835
1874
} else {
1836
- let ( _, descr_first, _) = & inaccessible_path_strings[ 0 ] ;
1875
+ let ( _, descr_first, _, _ ) = & inaccessible_path_strings[ 0 ] ;
1837
1876
let descr = if inaccessible_path_strings
1838
1877
. iter ( )
1839
1878
. skip ( 1 )
1840
- . all ( |( _, descr, _) | descr == descr_first)
1879
+ . all ( |( _, descr, _, _ ) | descr == descr_first)
1841
1880
{
1842
1881
descr_first. to_string ( )
1843
1882
} else {
@@ -1848,7 +1887,7 @@ crate fn show_candidates(
1848
1887
let mut has_colon = false ;
1849
1888
1850
1889
let mut spans = Vec :: new ( ) ;
1851
- for ( name, _, def_id) in & inaccessible_path_strings {
1890
+ for ( name, _, def_id, _ ) in & inaccessible_path_strings {
1852
1891
if let Some ( local_def_id) = def_id. and_then ( |did| did. as_local ( ) ) {
1853
1892
let span = definitions. def_span ( local_def_id) ;
1854
1893
let span = session. source_map ( ) . guess_head_span ( span) ;
@@ -1868,6 +1907,10 @@ crate fn show_candidates(
1868
1907
multi_span. push_span_label ( span, format ! ( "`{}`: not accessible" , name) ) ;
1869
1908
}
1870
1909
1910
+ for note in inaccessible_path_strings. iter ( ) . map ( |cand| cand. 3 . as_ref ( ) ) . flatten ( ) {
1911
+ err. note ( note) ;
1912
+ }
1913
+
1871
1914
err. span_note ( multi_span, & msg) ;
1872
1915
}
1873
1916
}
0 commit comments