@@ -2783,33 +2783,65 @@ fn show_candidates(
27832783 // by iterating through a hash map, so make sure they are ordered:
27842784 for path_strings in [ & mut accessible_path_strings, & mut inaccessible_path_strings] {
27852785 path_strings. sort_by ( |a, b| a. 0 . cmp ( & b. 0 ) ) ;
2786+ path_strings. dedup_by ( |a, b| a. 0 == b. 0 ) ;
27862787 let core_path_strings =
27872788 path_strings. extract_if ( |p| p. 0 . starts_with ( "core::" ) ) . collect :: < Vec < _ > > ( ) ;
2788- path_strings. extend ( core_path_strings) ;
2789- path_strings. dedup_by ( |a, b| a. 0 == b. 0 ) ;
2789+ let std_path_strings =
2790+ path_strings. extract_if ( |p| p. 0 . starts_with ( "std::" ) ) . collect :: < Vec < _ > > ( ) ;
2791+ let foreign_crate_path_strings =
2792+ path_strings. extract_if ( |p| !p. 0 . starts_with ( "crate::" ) ) . collect :: < Vec < _ > > ( ) ;
2793+
2794+ // We list the `crate` local paths first.
2795+ // Then we list the `std`/`core` paths.
2796+ if std_path_strings. len ( ) == core_path_strings. len ( ) {
2797+ // Do not list `core::` paths if we are already listing the `std::` ones.
2798+ path_strings. extend ( std_path_strings) ;
2799+ } else {
2800+ path_strings. extend ( std_path_strings) ;
2801+ path_strings. extend ( core_path_strings) ;
2802+ }
2803+ // List all paths from foreign crates last.
2804+ path_strings. extend ( foreign_crate_path_strings) ;
27902805 }
2791- accessible_path_strings. sort ( ) ;
27922806
27932807 if !accessible_path_strings. is_empty ( ) {
2794- let ( determiner, kind, name, through) =
2808+ let ( determiner, kind, s , name, through) =
27952809 if let [ ( name, descr, _, _, via_import) ] = & accessible_path_strings[ ..] {
27962810 (
27972811 "this" ,
27982812 * descr,
2813+ "" ,
27992814 format ! ( " `{name}`" ) ,
28002815 if * via_import { " through its public re-export" } else { "" } ,
28012816 )
28022817 } else {
2803- ( "one of these" , "items" , String :: new ( ) , "" )
2818+ // Get the unique item kinds and if there's only one, we use the right kind name
2819+ // instead of the more generic "items".
2820+ let mut kinds = accessible_path_strings
2821+ . iter ( )
2822+ . map ( |( _, descr, _, _, _) | * descr)
2823+ . collect :: < FxHashSet < & str > > ( )
2824+ . into_iter ( ) ;
2825+ let kind = if let Some ( kind) = kinds. next ( )
2826+ && let None = kinds. next ( )
2827+ {
2828+ kind
2829+ } else {
2830+ "item"
2831+ } ;
2832+ let s = if kind. ends_with ( 's' ) { "es" } else { "s" } ;
2833+
2834+ ( "one of these" , kind, s, String :: new ( ) , "" )
28042835 } ;
28052836
28062837 let instead = if let Instead :: Yes = instead { " instead" } else { "" } ;
28072838 let mut msg = if let DiagMode :: Pattern = mode {
28082839 format ! (
2809- "if you meant to match on {kind}{instead}{name}, use the full path in the pattern" ,
2840+ "if you meant to match on {kind}{s}{instead}{name}, use the full path in the \
2841+ pattern",
28102842 )
28112843 } else {
2812- format ! ( "consider importing {determiner} {kind}{through}{instead}" )
2844+ format ! ( "consider importing {determiner} {kind}{s}{ through}{instead}" )
28132845 } ;
28142846
28152847 for note in accessible_path_strings. iter ( ) . flat_map ( |cand| cand. 3 . as_ref ( ) ) {
0 commit comments