@@ -2783,33 +2783,56 @@ 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) =
2795- if let [ ( name, descr, _, _, via_import) ] = & accessible_path_strings[ ..] {
2796- (
2797- "this" ,
2798- * descr,
2799- format ! ( " `{name}`" ) ,
2800- if * via_import { " through its public re-export" } else { "" } ,
2801- )
2802- } else {
2803- ( "one of these" , "items" , String :: new ( ) , "" )
2804- } ;
2808+ let ( determiner, kind, s, name, through) = if let [ ( name, descr, _, _, via_import) ] =
2809+ & accessible_path_strings[ ..]
2810+ {
2811+ (
2812+ "this" ,
2813+ * descr,
2814+ "" ,
2815+ format ! ( " `{name}`" ) ,
2816+ if * via_import { " through its public re-export" } else { "" } ,
2817+ )
2818+ } else {
2819+ let descr_set: FxHashSet < & str > =
2820+ accessible_path_strings. iter ( ) . map ( |( _, descr, _, _, _) | * descr) . collect ( ) ;
2821+ let items =
2822+ if descr_set. len ( ) == 1 { descr_set. into_iter ( ) . next ( ) . unwrap ( ) } else { "item" } ;
2823+ let s = if items. ends_with ( 's' ) { "es" } else { "s" } ;
2824+
2825+ ( "one of these" , items, s, String :: new ( ) , "" )
2826+ } ;
28052827
28062828 let instead = if let Instead :: Yes = instead { " instead" } else { "" } ;
28072829 let mut msg = if let DiagMode :: Pattern = mode {
28082830 format ! (
2809- "if you meant to match on {kind}{instead}{name}, use the full path in the pattern" ,
2831+ "if you meant to match on {kind}{s}{instead}{name}, use the full path in the \
2832+ pattern",
28102833 )
28112834 } else {
2812- format ! ( "consider importing {determiner} {kind}{through}{instead}" )
2835+ format ! ( "consider importing {determiner} {kind}{s}{ through}{instead}" )
28132836 } ;
28142837
28152838 for note in accessible_path_strings. iter ( ) . flat_map ( |cand| cand. 3 . as_ref ( ) ) {
0 commit comments