@@ -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,11 @@ crate fn show_candidates(
17921823 let instead = if instead { " instead" } else { "" } ;
17931824 let mut msg = format ! ( "consider importing {} {}{}" , determiner, kind, instead) ;
17941825
1826+ // Issue notes
1827+ for note in accessible_path_strings. iter ( ) . map ( |cand| cand. 3 . as_ref ( ) ) . flatten ( ) {
1828+ err. note ( note) ;
1829+ }
1830+
17951831 if let Some ( span) = use_placement_span {
17961832 for candidate in & mut accessible_path_strings {
17971833 // produce an additional newline to separate the new use statement
@@ -1820,7 +1856,7 @@ crate fn show_candidates(
18201856 assert ! ( !inaccessible_path_strings. is_empty( ) ) ;
18211857
18221858 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 ] ;
18241860 let msg = format ! ( "{} `{}` exists but is inaccessible" , descr, name) ;
18251861
18261862 if let Some ( local_def_id) = def_id. and_then ( |did| did. as_local ( ) ) {
@@ -1832,12 +1868,15 @@ crate fn show_candidates(
18321868 } else {
18331869 err. note ( & msg) ;
18341870 }
1871+ if let Some ( note) = ( * note) . as_deref ( ) {
1872+ err. note ( note) ;
1873+ }
18351874 } else {
1836- let ( _, descr_first, _) = & inaccessible_path_strings[ 0 ] ;
1875+ let ( _, descr_first, _, _ ) = & inaccessible_path_strings[ 0 ] ;
18371876 let descr = if inaccessible_path_strings
18381877 . iter ( )
18391878 . skip ( 1 )
1840- . all ( |( _, descr, _) | descr == descr_first)
1879+ . all ( |( _, descr, _, _ ) | descr == descr_first)
18411880 {
18421881 descr_first. to_string ( )
18431882 } else {
@@ -1848,7 +1887,7 @@ crate fn show_candidates(
18481887 let mut has_colon = false ;
18491888
18501889 let mut spans = Vec :: new ( ) ;
1851- for ( name, _, def_id) in & inaccessible_path_strings {
1890+ for ( name, _, def_id, _ ) in & inaccessible_path_strings {
18521891 if let Some ( local_def_id) = def_id. and_then ( |did| did. as_local ( ) ) {
18531892 let span = definitions. def_span ( local_def_id) ;
18541893 let span = session. source_map ( ) . guess_head_span ( span) ;
@@ -1868,6 +1907,10 @@ crate fn show_candidates(
18681907 multi_span. push_span_label ( span, format ! ( "`{}`: not accessible" , name) ) ;
18691908 }
18701909
1910+ for note in inaccessible_path_strings. iter ( ) . map ( |cand| cand. 3 . as_ref ( ) ) . flatten ( ) {
1911+ err. note ( note) ;
1912+ }
1913+
18711914 err. span_note ( multi_span, & msg) ;
18721915 }
18731916 }
0 commit comments