@@ -66,6 +66,8 @@ crate struct ImportSuggestion {
6666 pub descr : & ' static str ,
6767 pub path : Path ,
6868 pub accessible : bool ,
69+ /// An extra note that should be issued if this item is suggested
70+ pub note : Option < String > ,
6971}
7072
7173/// Adjust the impl span so that just the `impl` keyword is taken by removing
@@ -872,11 +874,38 @@ impl<'a> Resolver<'a> {
872874 }
873875
874876 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+
875903 candidates. push ( ImportSuggestion {
876904 did,
877905 descr : res. descr ( ) ,
878906 path,
879907 accessible : child_accessible,
908+ note,
880909 } ) ;
881910 }
882911 }
@@ -1764,12 +1793,14 @@ crate fn show_candidates(
17641793 return ;
17651794 }
17661795
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 ( ) ;
17691800
17701801 candidates. iter ( ) . for_each ( |c| {
17711802 ( 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 ) )
17731804 } ) ;
17741805
17751806 // we want consistent results across executions, but candidates are produced
@@ -1792,6 +1823,10 @@ crate fn show_candidates(
17921823 let instead = if instead { " instead" } else { "" } ;
17931824 let mut msg = format ! ( "consider importing {} {}{}" , determiner, kind, instead) ;
17941825
1826+ for note in accessible_path_strings. iter ( ) . map ( |cand| cand. 3 . as_ref ( ) ) . flatten ( ) {
1827+ err. note ( note) ;
1828+ }
1829+
17951830 if let Some ( span) = use_placement_span {
17961831 for candidate in & mut accessible_path_strings {
17971832 // produce an additional newline to separate the new use statement
@@ -1820,7 +1855,7 @@ crate fn show_candidates(
18201855 assert ! ( !inaccessible_path_strings. is_empty( ) ) ;
18211856
18221857 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 ] ;
18241859 let msg = format ! ( "{} `{}` exists but is inaccessible" , descr, name) ;
18251860
18261861 if let Some ( local_def_id) = def_id. and_then ( |did| did. as_local ( ) ) {
@@ -1832,12 +1867,15 @@ crate fn show_candidates(
18321867 } else {
18331868 err. note ( & msg) ;
18341869 }
1870+ if let Some ( note) = ( * note) . as_deref ( ) {
1871+ err. note ( note) ;
1872+ }
18351873 } else {
1836- let ( _, descr_first, _) = & inaccessible_path_strings[ 0 ] ;
1874+ let ( _, descr_first, _, _ ) = & inaccessible_path_strings[ 0 ] ;
18371875 let descr = if inaccessible_path_strings
18381876 . iter ( )
18391877 . skip ( 1 )
1840- . all ( |( _, descr, _) | descr == descr_first)
1878+ . all ( |( _, descr, _, _ ) | descr == descr_first)
18411879 {
18421880 descr_first. to_string ( )
18431881 } else {
@@ -1848,7 +1886,7 @@ crate fn show_candidates(
18481886 let mut has_colon = false ;
18491887
18501888 let mut spans = Vec :: new ( ) ;
1851- for ( name, _, def_id) in & inaccessible_path_strings {
1889+ for ( name, _, def_id, _ ) in & inaccessible_path_strings {
18521890 if let Some ( local_def_id) = def_id. and_then ( |did| did. as_local ( ) ) {
18531891 let span = definitions. def_span ( local_def_id) ;
18541892 let span = session. source_map ( ) . guess_head_span ( span) ;
@@ -1868,6 +1906,10 @@ crate fn show_candidates(
18681906 multi_span. push_span_label ( span, format ! ( "`{}`: not accessible" , name) ) ;
18691907 }
18701908
1909+ for note in inaccessible_path_strings. iter ( ) . map ( |cand| cand. 3 . as_ref ( ) ) . flatten ( ) {
1910+ err. note ( note) ;
1911+ }
1912+
18711913 err. span_note ( multi_span, & msg) ;
18721914 }
18731915 }
0 commit comments