Skip to content

Commit 5de8e6e

Browse files
committed
Tweak output of import suggestions
When both `std::` and `core::` items are available, only suggest the `std::` ones. We ensure that in `no_std` crates we suggest `core::` items. Ensure that the list of items suggested to be imported are always in the order of local crate items, `std`/`core` items and finally foreign crate items. Tweak wording of import suggestion: if there are multiple items but they are all of the same kind, we use the kind name and not the generic "items". Fix #83564.
1 parent f158600 commit 5de8e6e

30 files changed

+159
-80
lines changed

compiler/rustc_resolve/src/diagnostics.rs

+39-7
Original file line numberDiff line numberDiff line change
@@ -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()) {

src/tools/clippy/tests/ui/crashes/ice-6252.stderr

+1-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ error[E0412]: cannot find type `PhantomData` in this scope
44
LL | _n: PhantomData,
55
| ^^^^^^^^^^^ not found in this scope
66
|
7-
help: consider importing one of these items
8-
|
9-
LL + use core::marker::PhantomData;
7+
help: consider importing this struct
108
|
119
LL + use std::marker::PhantomData;
1210
|

tests/ui/const-generics/issues/issue-82956.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0433]: failed to resolve: use of undeclared type `IntoIter`
44
LL | let mut iter = IntoIter::new(self);
55
| ^^^^^^^^ use of undeclared type `IntoIter`
66
|
7-
help: consider importing one of these items
7+
help: consider importing one of these structs
88
|
99
LL + use std::array::IntoIter;
1010
|

tests/ui/consts/const_refs_to_static-ice-121413.rs

+4
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,16 @@
55
// ignore-tidy-linelength
66
#![feature(const_refs_to_static)]
77
const REF_INTERIOR_MUT: &usize = {
8+
//~^ HELP consider importing this struct
89
static FOO: Sync = AtomicUsize::new(0);
910
//~^ ERROR failed to resolve: use of undeclared type `AtomicUsize`
1011
//~| WARN trait objects without an explicit `dyn` are deprecated
1112
//~| ERROR the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time
1213
//~| ERROR the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time
1314
//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
15+
//~| HELP if this is an object-safe trait, use `dyn`
16+
//~| HELP the trait `Sized` is not implemented for `(dyn Sync + 'static)`
17+
//~| HELP the trait `Sized` is not implemented for `(dyn Sync + 'static)`
1418
unsafe { &*(&FOO as *const _ as *const usize) }
1519
};
1620
pub fn main() {}

tests/ui/consts/const_refs_to_static-ice-121413.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0433]: failed to resolve: use of undeclared type `AtomicUsize`
2-
--> $DIR/const_refs_to_static-ice-121413.rs:8:24
2+
--> $DIR/const_refs_to_static-ice-121413.rs:9:24
33
|
44
LL | static FOO: Sync = AtomicUsize::new(0);
55
| ^^^^^^^^^^^ use of undeclared type `AtomicUsize`
@@ -10,7 +10,7 @@ LL + use std::sync::atomic::AtomicUsize;
1010
|
1111

1212
warning: trait objects without an explicit `dyn` are deprecated
13-
--> $DIR/const_refs_to_static-ice-121413.rs:8:17
13+
--> $DIR/const_refs_to_static-ice-121413.rs:9:17
1414
|
1515
LL | static FOO: Sync = AtomicUsize::new(0);
1616
| ^^^^
@@ -24,15 +24,15 @@ LL | static FOO: dyn Sync = AtomicUsize::new(0);
2424
| +++
2525

2626
error[E0277]: the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time
27-
--> $DIR/const_refs_to_static-ice-121413.rs:8:17
27+
--> $DIR/const_refs_to_static-ice-121413.rs:9:17
2828
|
2929
LL | static FOO: Sync = AtomicUsize::new(0);
3030
| ^^^^ doesn't have a size known at compile-time
3131
|
3232
= help: the trait `Sized` is not implemented for `(dyn Sync + 'static)`
3333

3434
error[E0277]: the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time
35-
--> $DIR/const_refs_to_static-ice-121413.rs:8:24
35+
--> $DIR/const_refs_to_static-ice-121413.rs:9:24
3636
|
3737
LL | static FOO: Sync = AtomicUsize::new(0);
3838
| ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time

tests/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ error[E0425]: cannot find value `Set` in this scope
2222
LL | fn setup() -> Set { Set }
2323
| ^^^ not found in this scope
2424
|
25-
help: consider importing one of these items
25+
help: consider importing one of these unit variants
2626
|
2727
LL + use AffixHeart::Set;
2828
|

tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr

+2-5
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ LL | fn f() { my_core::mem::drop(0); }
2424
LL | a!();
2525
| ---- in this macro invocation
2626
|
27-
= help: consider importing one of these items:
28-
core::mem
27+
= help: consider importing this module:
2928
std::mem
3029
= note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info)
3130

@@ -35,9 +34,7 @@ error[E0433]: failed to resolve: use of undeclared crate or module `my_core`
3534
LL | fn f() { my_core::mem::drop(0); }
3635
| ^^^^^^^ use of undeclared crate or module `my_core`
3736
|
38-
help: consider importing one of these items
39-
|
40-
LL + use core::mem;
37+
help: consider importing this module
4138
|
4239
LL + use std::mem;
4340
|

tests/ui/imports/cycle-import-in-std-1.stderr

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ error[E0432]: unresolved import `ops`
44
LL | use ops::{self as std};
55
| ^^^^^^^^^^^ no external crate `ops`
66
|
7-
= help: consider importing one of these items instead:
8-
core::ops
7+
= help: consider importing this module instead:
98
std::ops
109

1110
error: aborting due to 1 previous error

tests/ui/imports/cycle-import-in-std-2.stderr

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ error[E0432]: unresolved import `ops`
44
LL | use ops::{self as std};
55
| ^^^^^^^^^^^ no external crate `ops`
66
|
7-
= help: consider importing one of these items instead:
8-
core::ops
7+
= help: consider importing this module instead:
98
std::ops
109

1110
error: aborting due to 1 previous error

tests/ui/imports/import-alias-issue-121168.edition2018.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0412]: cannot find type `Foo` in this scope
44
LL | let _: Foo<i32> = todo!();
55
| ^^^ not found in this scope
66
|
7-
help: consider importing one of these items
7+
help: consider importing one of these structs
88
|
99
LL + use crate::nice_crate_name::Foo;
1010
|

tests/ui/imports/import-alias-issue-121168.edition2021.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0412]: cannot find type `Foo` in this scope
44
LL | let _: Foo<i32> = todo!();
55
| ^^^ not found in this scope
66
|
7-
help: consider importing one of these items
7+
help: consider importing one of these structs
88
|
99
LL + use crate::nice_crate_name::Foo;
1010
|

tests/ui/imports/issue-56125.stderr

+5-5
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ error[E0432]: unresolved import `empty::issue_56125`
44
LL | use empty::issue_56125;
55
| ^^^^^^^^^^^^^^^^^^ no `issue_56125` in `m3::empty`
66
|
7-
help: consider importing one of these items instead
7+
help: consider importing one of these modules instead
88
|
9+
LL | use crate::m3::last_segment::issue_56125;
10+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11+
LL | use crate::m3::non_last_segment::non_last_segment::issue_56125;
12+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
913
LL | use ::issue_56125::issue_56125;
1014
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
1115
LL | use ::issue_56125::last_segment::issue_56125;
1216
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
13-
LL | use ::issue_56125::non_last_segment::non_last_segment::issue_56125;
14-
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
15-
LL | use crate::m3::last_segment::issue_56125;
16-
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1717
and 1 other candidate
1818

1919
error[E0659]: `issue_56125` is ambiguous

tests/ui/lint/use_suggestion_json.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ mod foo {
9595
],
9696
"children": [
9797
{
98-
"message": "consider importing one of these items",
98+
"message": "consider importing one of these structs",
9999
"code": null,
100100
"level": "help",
101101
"spans": [
@@ -386,7 +386,7 @@ mod foo {
386386
\u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m let x: Iter;\u001b[0m
387387
\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9m^^^^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9mnot found in this scope\u001b[0m
388388
\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m
389-
\u001b[0m\u001b[1m\u001b[38;5;14mhelp\u001b[0m\u001b[0m: consider importing one of these items\u001b[0m
389+
\u001b[0m\u001b[1m\u001b[38;5;14mhelp\u001b[0m\u001b[0m: consider importing one of these structs\u001b[0m
390390
\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m
391391
\u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[38;5;10m+ use std::collections::binary_heap::Iter;\u001b[0m
392392
\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m

tests/ui/namespace/namespace-mix.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ help: a tuple struct with a similar name exists
1212
|
1313
LL | check(m1::TS);
1414
| ~~
15-
help: consider importing one of these items instead
15+
help: consider importing one of these constants instead
1616
|
1717
LL + use m2::S;
1818
|
@@ -40,7 +40,7 @@ help: a tuple struct with a similar name exists
4040
|
4141
LL | check(xm1::TS);
4242
| ~~
43-
help: consider importing one of these items instead
43+
help: consider importing one of these constants instead
4444
|
4545
LL + use m2::S;
4646
|
@@ -66,7 +66,7 @@ help: a tuple variant with a similar name exists
6666
|
6767
LL | check(m7::TV);
6868
| ~~
69-
help: consider importing one of these items instead
69+
help: consider importing one of these constants instead
7070
|
7171
LL + use m8::V;
7272
|
@@ -94,7 +94,7 @@ help: a tuple variant with a similar name exists
9494
|
9595
LL | check(xm7::TV);
9696
| ~~
97-
help: consider importing one of these items instead
97+
help: consider importing one of these constants instead
9898
|
9999
LL + use m8::V;
100100
|

tests/ui/resolve/issue-16058.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0574]: expected struct, variant or union type, found enum `Result`
44
LL | Result {
55
| ^^^^^^ not a struct, variant or union type
66
|
7-
help: consider importing one of these items instead
7+
help: consider importing one of these type aliases instead
88
|
99
LL + use std::fmt::Result;
1010
|

tests/ui/resolve/issue-21221-1.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,29 @@ error[E0405]: cannot find trait `Mul` in this scope
44
LL | impl Mul for Foo {
55
| ^^^ not found in this scope
66
|
7-
help: consider importing one of these items
7+
help: consider importing one of these traits
8+
|
9+
LL + use std::ops::Mul;
810
|
911
LL + use mul1::Mul;
1012
|
1113
LL + use mul2::Mul;
1214
|
13-
LL + use std::ops::Mul;
14-
|
1515

1616
error[E0412]: cannot find type `Mul` in this scope
1717
--> $DIR/issue-21221-1.rs:58:16
1818
|
1919
LL | fn getMul() -> Mul {
2020
| ^^^ not found in this scope
2121
|
22-
help: consider importing one of these items
22+
help: consider importing one of these traits
23+
|
24+
LL + use std::ops::Mul;
2325
|
2426
LL + use mul1::Mul;
2527
|
2628
LL + use mul2::Mul;
2729
|
28-
LL + use std::ops::Mul;
29-
|
3030

3131
error[E0405]: cannot find trait `ThisTraitReallyDoesntExistInAnyModuleReally` in this scope
3232
--> $DIR/issue-21221-1.rs:63:6

tests/ui/resolve/issue-21221-2.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0405]: cannot find trait `T` in this scope
44
LL | impl T for Foo { }
55
| ^ not found in this scope
66
|
7-
help: consider importing one of these items
7+
help: consider importing one of these traits
88
|
99
LL + use baz::T;
1010
|

tests/ui/resolve/issue-50599.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0425]: cannot find value `LOG10_2` in module `std::f64`
44
LL | const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize;
55
| ^^^^^^^ not found in `std::f64`
66
|
7-
help: consider importing one of these items
7+
help: consider importing one of these constants
88
|
99
LL + use std::f128::consts::LOG10_2;
1010
|

tests/ui/resolve/issue-73427.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ help: the following enum variant is available
105105
|
106106
LL | (E::TupleWithFields(/* fields */)).foo();
107107
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
108-
help: consider importing one of these items instead
108+
help: consider importing one of these constants instead
109109
|
110110
LL + use std::f128::consts::E;
111111
|

tests/ui/resolve/privacy-enum-ctor.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ help: a function with a similar name exists
8282
|
8383
LL | let _: E = m::f;
8484
| ~
85-
help: consider importing one of these items instead
85+
help: consider importing one of these constants instead
8686
|
8787
LL + use std::f128::consts::E;
8888
|
@@ -123,7 +123,7 @@ help: alternatively, the following enum variant is available
123123
|
124124
LL | let _: E = (E::Fn(/* fields */));
125125
| ~~~~~~~~~~~~~~~~~~~~~
126-
help: consider importing one of these items instead
126+
help: consider importing one of these constants instead
127127
|
128128
LL + use std::f128::consts::E;
129129
|

tests/ui/rfcs/rfc-2126-extern-absolute-paths/not-allowed.stderr

+1-3
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@ error[E0432]: unresolved import `alloc`
44
LL | use alloc;
55
| ^^^^^ no external crate `alloc`
66
|
7-
help: consider importing one of these items instead
7+
help: consider importing this module instead
88
|
9-
LL | use core::alloc;
10-
| ~~~~~~~~~~~
119
LL | use std::alloc;
1210
| ~~~~~~~~~~
1311

tests/ui/rust-2018/issue-52202-use-suggestions.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0422]: cannot find struct, variant or union type `Drain` in this scope
44
LL | let _d = Drain {};
55
| ^^^^^ not found in this scope
66
|
7-
help: consider importing one of these items
7+
help: consider importing one of these structs
88
|
99
LL + use crate::plumbing::Drain;
1010
|

0 commit comments

Comments
 (0)