@@ -2783,33 +2783,65 @@ fn show_candidates(
2783
2783
// by iterating through a hash map, so make sure they are ordered:
2784
2784
for path_strings in [ & mut accessible_path_strings, & mut inaccessible_path_strings] {
2785
2785
path_strings. sort_by ( |a, b| a. 0 . cmp ( & b. 0 ) ) ;
2786
+ path_strings. dedup_by ( |a, b| a. 0 == b. 0 ) ;
2786
2787
let core_path_strings =
2787
2788
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) ;
2790
2805
}
2791
- accessible_path_strings. sort ( ) ;
2792
2806
2793
2807
if !accessible_path_strings. is_empty ( ) {
2794
- let ( determiner, kind, name, through) =
2808
+ let ( determiner, kind, s , name, through) =
2795
2809
if let [ ( name, descr, _, _, via_import) ] = & accessible_path_strings[ ..] {
2796
2810
(
2797
2811
"this" ,
2798
2812
* descr,
2813
+ "" ,
2799
2814
format ! ( " `{name}`" ) ,
2800
2815
if * via_import { " through its public re-export" } else { "" } ,
2801
2816
)
2802
2817
} 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 ( ) , "" )
2804
2835
} ;
2805
2836
2806
2837
let instead = if let Instead :: Yes = instead { " instead" } else { "" } ;
2807
2838
let mut msg = if let DiagMode :: Pattern = mode {
2808
2839
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",
2810
2842
)
2811
2843
} else {
2812
- format ! ( "consider importing {determiner} {kind}{through}{instead}" )
2844
+ format ! ( "consider importing {determiner} {kind}{s}{ through}{instead}" )
2813
2845
} ;
2814
2846
2815
2847
for note in accessible_path_strings. iter ( ) . flat_map ( |cand| cand. 3 . as_ref ( ) ) {
0 commit comments